Search in sources :

Example 1 with JoinableClause

use of org.apache.druid.segment.join.JoinableClause in project druid by druid-io.

the class JoinableClauses method createClauses.

/**
 * Builds a list of {@link JoinableClause} corresponding to a list of {@link PreJoinableClause}. This will call
 * {@link JoinableFactory#build} on each one and therefore may be an expensive operation.
 */
public static JoinableClauses createClauses(final List<PreJoinableClause> preClauses, final JoinableFactory joinableFactory) {
    // Since building a JoinableClause can be expensive, check for prefix conflicts before building
    checkPreJoinableClausesForDuplicatesAndShadowing(preClauses);
    List<JoinableClause> joinableClauses = preClauses.stream().map(preJoinableClause -> {
        final Optional<Joinable> joinable = joinableFactory.build(preJoinableClause.getDataSource(), preJoinableClause.getCondition());
        return new JoinableClause(preJoinableClause.getPrefix(), joinable.orElseThrow(() -> new ISE("dataSource is not joinable: %s", preJoinableClause.getDataSource())), preJoinableClause.getJoinType(), preJoinableClause.getCondition());
    }).collect(Collectors.toList());
    return new JoinableClauses(joinableClauses);
}
Also used : VirtualColumns(org.apache.druid.segment.VirtualColumns) Joinable(org.apache.druid.segment.join.Joinable) PreJoinableClause(org.apache.druid.query.planning.PreJoinableClause) JoinableClause(org.apache.druid.segment.join.JoinableClause) VirtualColumn(org.apache.druid.segment.VirtualColumn) Collection(java.util.Collection) ISE(org.apache.druid.java.util.common.ISE) JoinableFactory(org.apache.druid.segment.join.JoinableFactory) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) List(java.util.List) Optional(java.util.Optional) Nonnull(javax.annotation.Nonnull) JoinPrefixUtils(org.apache.druid.segment.join.JoinPrefixUtils) Nullable(javax.annotation.Nullable) Optional(java.util.Optional) ISE(org.apache.druid.java.util.common.ISE) PreJoinableClause(org.apache.druid.query.planning.PreJoinableClause) JoinableClause(org.apache.druid.segment.join.JoinableClause)

Example 2 with JoinableClause

use of org.apache.druid.segment.join.JoinableClause in project druid by druid-io.

the class JoinAndLookupBenchmark method setup.

@Setup()
public void setup() throws IOException {
    tmpDir = FileUtils.createTempDir();
    ColumnConfig columnConfig = () -> columnCacheSizeBytes;
    index = JoinTestHelper.createFactIndexBuilder(columnConfig, tmpDir, rows).buildMMappedIndex();
    final String prefix = "c.";
    baseSegment = new QueryableIndexSegment(index, SegmentId.dummy("join"));
    List<JoinableClause> joinableClausesLookupStringKey = ImmutableList.of(new JoinableClause(prefix, LookupJoinable.wrap(JoinTestHelper.createCountryIsoCodeToNameLookup()), JoinType.LEFT, JoinConditionAnalysis.forExpression(StringUtils.format("countryIsoCode == \"%sk\"", prefix), prefix, ExprMacroTable.nil())));
    JoinFilterPreAnalysis preAnalysisLookupStringKey = JoinFilterAnalyzer.computeJoinFilterPreAnalysis(new JoinFilterPreAnalysisKey(new JoinFilterRewriteConfig(false, false, false, false, 0), joinableClausesLookupStringKey, VirtualColumns.EMPTY, null));
    hashJoinLookupStringKeySegment = new HashJoinSegment(ReferenceCountingSegment.wrapRootGenerationSegment(baseSegment), null, joinableClausesLookupStringKey, preAnalysisLookupStringKey);
    List<JoinableClause> joinableClausesLookupLongKey = ImmutableList.of(new JoinableClause(prefix, LookupJoinable.wrap(JoinTestHelper.createCountryIsoCodeToNameLookup()), JoinType.LEFT, JoinConditionAnalysis.forExpression(StringUtils.format("countryIsoCode == \"%sk\"", prefix), prefix, ExprMacroTable.nil())));
    JoinFilterPreAnalysis preAnalysisLookupLongKey = JoinFilterAnalyzer.computeJoinFilterPreAnalysis(new JoinFilterPreAnalysisKey(new JoinFilterRewriteConfig(false, false, false, false, 0), joinableClausesLookupLongKey, VirtualColumns.EMPTY, null));
    hashJoinLookupLongKeySegment = new HashJoinSegment(ReferenceCountingSegment.wrapRootGenerationSegment(baseSegment), null, joinableClausesLookupLongKey, preAnalysisLookupLongKey);
    List<JoinableClause> joinableClausesIndexedTableStringKey = ImmutableList.of(new JoinableClause(prefix, new IndexedTableJoinable(JoinTestHelper.createCountriesIndexedTable()), JoinType.LEFT, JoinConditionAnalysis.forExpression(StringUtils.format("countryIsoCode == \"%scountryIsoCode\"", prefix), prefix, ExprMacroTable.nil())));
    JoinFilterPreAnalysis preAnalysisIndexedStringKey = JoinFilterAnalyzer.computeJoinFilterPreAnalysis(new JoinFilterPreAnalysisKey(new JoinFilterRewriteConfig(false, false, false, false, 0), joinableClausesLookupLongKey, VirtualColumns.EMPTY, null));
    hashJoinIndexedTableStringKeySegment = new HashJoinSegment(ReferenceCountingSegment.wrapRootGenerationSegment(baseSegment), null, joinableClausesIndexedTableStringKey, preAnalysisIndexedStringKey);
    List<JoinableClause> joinableClausesIndexedTableLongKey = ImmutableList.of(new JoinableClause(prefix, new IndexedTableJoinable(JoinTestHelper.createCountriesIndexedTable()), JoinType.LEFT, JoinConditionAnalysis.forExpression(StringUtils.format("countryNumber == \"%scountryNumber\"", prefix), prefix, ExprMacroTable.nil())));
    JoinFilterPreAnalysis preAnalysisIndexedLongKey = JoinFilterAnalyzer.computeJoinFilterPreAnalysis(new JoinFilterPreAnalysisKey(new JoinFilterRewriteConfig(false, false, false, false, 0), joinableClausesIndexedTableLongKey, VirtualColumns.EMPTY, null));
    hashJoinIndexedTableLongKeySegment = new HashJoinSegment(ReferenceCountingSegment.wrapRootGenerationSegment(baseSegment), null, joinableClausesIndexedTableLongKey, preAnalysisIndexedLongKey);
    final Map<String, String> countryCodeToNameMap = JoinTestHelper.createCountryIsoCodeToNameLookup().getMap();
    final Map<String, String> countryNumberToNameMap = JoinTestHelper.createCountryNumberToNameLookup().getMap();
    final ExprMacroTable exprMacroTable = new ExprMacroTable(ImmutableList.of(new LookupExprMacro(new LookupExtractorFactoryContainerProvider() {

        @Override
        public Set<String> getAllLookupNames() {
            return ImmutableSet.of(LOOKUP_COUNTRY_CODE_TO_NAME, LOOKUP_COUNTRY_NUMBER_TO_NAME);
        }

        @Override
        public Optional<LookupExtractorFactoryContainer> get(String lookupName) {
            if (LOOKUP_COUNTRY_CODE_TO_NAME.equals(lookupName)) {
                return Optional.of(new LookupExtractorFactoryContainer("0", new MapLookupExtractorFactory(countryCodeToNameMap, false)));
            } else if (LOOKUP_COUNTRY_NUMBER_TO_NAME.equals(lookupName)) {
                return Optional.of(new LookupExtractorFactoryContainer("0", new MapLookupExtractorFactory(countryNumberToNameMap, false)));
            } else {
                return Optional.empty();
            }
        }
    })));
    lookupVirtualColumns = VirtualColumns.create(ImmutableList.of(new ExpressionVirtualColumn(LOOKUP_COUNTRY_CODE_TO_NAME, "lookup(countryIsoCode, '" + LOOKUP_COUNTRY_CODE_TO_NAME + "')", ColumnType.STRING, exprMacroTable), new ExpressionVirtualColumn(LOOKUP_COUNTRY_NUMBER_TO_NAME, "lookup(countryNumber, '" + LOOKUP_COUNTRY_NUMBER_TO_NAME + "')", ColumnType.STRING, exprMacroTable)));
}
Also used : QueryableIndexSegment(org.apache.druid.segment.QueryableIndexSegment) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) ColumnConfig(org.apache.druid.segment.column.ColumnConfig) Optional(java.util.Optional) MapLookupExtractorFactory(org.apache.druid.query.lookup.MapLookupExtractorFactory) JoinFilterPreAnalysisKey(org.apache.druid.segment.join.filter.JoinFilterPreAnalysisKey) LookupExprMacro(org.apache.druid.query.expression.LookupExprMacro) JoinFilterRewriteConfig(org.apache.druid.segment.join.filter.rewrite.JoinFilterRewriteConfig) ExprMacroTable(org.apache.druid.math.expr.ExprMacroTable) JoinableClause(org.apache.druid.segment.join.JoinableClause) HashJoinSegment(org.apache.druid.segment.join.HashJoinSegment) ExpressionVirtualColumn(org.apache.druid.segment.virtual.ExpressionVirtualColumn) JoinFilterPreAnalysis(org.apache.druid.segment.join.filter.JoinFilterPreAnalysis) IndexedTableJoinable(org.apache.druid.segment.join.table.IndexedTableJoinable) LookupExtractorFactoryContainerProvider(org.apache.druid.query.lookup.LookupExtractorFactoryContainerProvider) LookupExtractorFactoryContainer(org.apache.druid.query.lookup.LookupExtractorFactoryContainer) Setup(org.openjdk.jmh.annotations.Setup)

Example 3 with JoinableClause

use of org.apache.druid.segment.join.JoinableClause in project druid by druid-io.

the class IndexedTableJoinCursorBenchmark method setup.

@Setup(Level.Trial)
public void setup() {
    baseSegment = makeQueryableIndexSegment(closer, "regular", rowsPerSegment);
    joinSegment = makeQueryableIndexSegment(closer, "join", rowsPerTableSegment);
    table = closer.register(makeTable(indexedTableType, keyColumns, joinSegment));
    final String prefix = "j0.";
    projectionColumns = PROJECTIONS.get(projection);
    final String[] split = joinColumns.split(",");
    final String lhsJoinColumn = split[0];
    final String rhsJoinColumn = split[1];
    final List<JoinableClause> clauses = ImmutableList.of(new JoinableClause(prefix, new IndexedTableJoinable(table), JoinType.LEFT, JoinConditionAnalysis.forExpression(StringUtils.format("%s == \"%s%s\"", lhsJoinColumn, prefix, rhsJoinColumn), prefix, ExprMacroTable.nil())));
    final JoinFilterPreAnalysis preAnalysis = JoinFilterAnalyzer.computeJoinFilterPreAnalysis(new JoinFilterPreAnalysisKey(new JoinFilterRewriteConfig(enableFilterPushdown, enableFilterRewrite, enableFilterRewriteValueFilters, QueryContexts.DEFAULT_ENABLE_REWRITE_JOIN_TO_FILTER, QueryContexts.DEFAULT_ENABLE_JOIN_FILTER_REWRITE_MAX_SIZE), clauses, VirtualColumns.EMPTY, null));
    hashJoinSegment = closer.register(new HashJoinSegment(ReferenceCountingSegment.wrapRootGenerationSegment(baseSegment), null, clauses, preAnalysis));
}
Also used : HashJoinSegment(org.apache.druid.segment.join.HashJoinSegment) JoinFilterPreAnalysis(org.apache.druid.segment.join.filter.JoinFilterPreAnalysis) JoinFilterPreAnalysisKey(org.apache.druid.segment.join.filter.JoinFilterPreAnalysisKey) IndexedTableJoinable(org.apache.druid.segment.join.table.IndexedTableJoinable) JoinFilterRewriteConfig(org.apache.druid.segment.join.filter.rewrite.JoinFilterRewriteConfig) JoinableClause(org.apache.druid.segment.join.JoinableClause) Setup(org.openjdk.jmh.annotations.Setup)

Example 4 with JoinableClause

use of org.apache.druid.segment.join.JoinableClause in project druid by druid-io.

the class JoinFilterCorrelations method findCorrelatedBaseTableColumns.

/**
 * For each rhs column that appears in the equiconditions for a table's JoinableClause,
 * we try to determine what base table columns are related to the rhs column through the total set of equiconditions.
 * We do this by searching backwards through the chain of join equiconditions using the provided equicondition map.
 * <p>
 * For example, suppose we have 3 tables, A,B,C, joined with the following conditions, where A is the base table:
 * A.joinColumn == B.joinColumn
 * B.joinColum == C.joinColumnenableRewriteValueColumnFilters
 * <p>
 * We would determine that C.joinColumn is correlated with A.joinColumn: we first see that
 * C.joinColumn is linked to B.joinColumn which in turn is linked to A.joinColumn
 * <p>
 * Suppose we had the following join conditions instead:
 * f(A.joinColumn) == B.joinColumn
 * B.joinColum == C.joinColumn
 * In this case, the JoinFilterColumnCorrelationAnalysis for C.joinColumn would be linked to f(A.joinColumn).
 * <p>
 * Suppose we had the following join conditions instead:
 * A.joinColumn == B.joinColumn
 * f(B.joinColum) == C.joinColumn
 * <p>
 * Because we cannot reverse the function f() applied to the second table B in all cases,
 * we cannot relate C.joinColumn to A.joinColumn, and we would not generate a correlation for C.joinColumn
 *
 * @param joinableClauses     List of joinable clauses for the query
 * @param tablePrefix         Prefix for a join table
 * @param rhsRewriteCandidate RHS rewrite candidate that we find correlated base table columns for
 * @param equiConditions      Map of equiconditions, keyed by the right hand columns
 * @return A list of correlatation analyses for the equicondition RHS columns that reside in the table associated with
 * the tablePrefix
 */
private static Optional<Map<String, JoinFilterColumnCorrelationAnalysis>> findCorrelatedBaseTableColumns(JoinableClauses joinableClauses, String tablePrefix, RhsRewriteCandidate rhsRewriteCandidate, Equiconditions equiConditions) {
    JoinableClause clauseForTablePrefix = rhsRewriteCandidate.getJoinableClause();
    JoinConditionAnalysis jca = clauseForTablePrefix.getCondition();
    Set<String> rhsColumns = new HashSet<>();
    if (rhsRewriteCandidate.isDirectRewrite()) {
        // If we filter on a RHS join column, we only need to consider that column from the RHS side
        rhsColumns.add(rhsRewriteCandidate.getRhsColumn());
    } else {
        for (Equality eq : jca.getEquiConditions()) {
            rhsColumns.add(tablePrefix + eq.getRightColumn());
        }
    }
    Map<String, JoinFilterColumnCorrelationAnalysis> correlations = new LinkedHashMap<>();
    for (String rhsColumn : rhsColumns) {
        Set<String> correlatedBaseColumns = new HashSet<>();
        Set<Expr> correlatedBaseExpressions = new HashSet<>();
        getCorrelationForRHSColumn(joinableClauses, equiConditions, rhsColumn, correlatedBaseColumns, correlatedBaseExpressions);
        if (correlatedBaseColumns.isEmpty() && correlatedBaseExpressions.isEmpty()) {
            continue;
        }
        correlations.put(rhsColumn, new JoinFilterColumnCorrelationAnalysis(rhsColumn, correlatedBaseColumns, correlatedBaseExpressions));
    }
    if (correlations.size() == 0) {
        return Optional.empty();
    } else {
        return Optional.of(correlations);
    }
}
Also used : Expr(org.apache.druid.math.expr.Expr) JoinConditionAnalysis(org.apache.druid.segment.join.JoinConditionAnalysis) Equality(org.apache.druid.segment.join.Equality) JoinableClause(org.apache.druid.segment.join.JoinableClause) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap)

Example 5 with JoinableClause

use of org.apache.druid.segment.join.JoinableClause in project druid by druid-io.

the class RhsRewriteCandidates method determineRhsRewriteCandidatesForSingleFilter.

private static Optional<RhsRewriteCandidate> determineRhsRewriteCandidatesForSingleFilter(Filter orClause, Equiconditions equiconditions, JoinableClauses joinableClauses) {
    // Currently, we only support rewrites of filters that operate on a single column for simplicity.
    if (equiconditions.doesFilterSupportDirectJoinFilterRewrite(orClause)) {
        String reqColumn = orClause.getRequiredColumns().iterator().next();
        JoinableClause joinableClause = joinableClauses.getColumnFromJoinIfExists(reqColumn);
        if (joinableClause != null) {
            return Optional.of(new RhsRewriteCandidate(joinableClause, reqColumn, null, true));
        }
    } else if (orClause instanceof SelectorFilter) {
        // this is a candidate for RHS filter rewrite, determine column correlations and correlated values
        String reqColumn = ((SelectorFilter) orClause).getDimension();
        String reqValue = ((SelectorFilter) orClause).getValue();
        JoinableClause joinableClause = joinableClauses.getColumnFromJoinIfExists(reqColumn);
        if (joinableClause != null) {
            return Optional.of(new RhsRewriteCandidate(joinableClause, reqColumn, reqValue, false));
        }
    }
    return Optional.empty();
}
Also used : SelectorFilter(org.apache.druid.segment.filter.SelectorFilter) JoinableClause(org.apache.druid.segment.join.JoinableClause)

Aggregations

JoinableClause (org.apache.druid.segment.join.JoinableClause)5 Optional (java.util.Optional)2 HashJoinSegment (org.apache.druid.segment.join.HashJoinSegment)2 JoinFilterPreAnalysis (org.apache.druid.segment.join.filter.JoinFilterPreAnalysis)2 JoinFilterPreAnalysisKey (org.apache.druid.segment.join.filter.JoinFilterPreAnalysisKey)2 JoinFilterRewriteConfig (org.apache.druid.segment.join.filter.rewrite.JoinFilterRewriteConfig)2 IndexedTableJoinable (org.apache.druid.segment.join.table.IndexedTableJoinable)2 Setup (org.openjdk.jmh.annotations.Setup)2 ImmutableSet (com.google.common.collect.ImmutableSet)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Set (java.util.Set)1 Collectors (java.util.stream.Collectors)1 Nonnull (javax.annotation.Nonnull)1 Nullable (javax.annotation.Nullable)1 ISE (org.apache.druid.java.util.common.ISE)1 Expr (org.apache.druid.math.expr.Expr)1