Search in sources :

Example 1 with LOCAL

use of com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL in project presto by prestodb.

the class TestValidateAggregationsWithDefaultValues method testWithPartialAggregationBelowJoin.

@Test
public void testWithPartialAggregationBelowJoin() {
    PlanNode root = builder.aggregation(af -> af.step(FINAL).groupingSets(groupingSets(ImmutableList.of(variable), 2, ImmutableSet.of(0))).source(builder.join(INNER, builder.exchange(e -> e.type(REPARTITION).scope(LOCAL).fixedHashDistributionParitioningScheme(ImmutableList.of(variable), ImmutableList.of(variable)).addInputsSet(variable).addSource(builder.aggregation(ap -> ap.step(PARTIAL).groupingSets(groupingSets(ImmutableList.of(variable), 2, ImmutableSet.of(0))).source(tableScanNode)))), builder.values())));
    validatePlan(root, true);
}
Also used : WarningCollector(com.facebook.presto.spi.WarningCollector) BasePlanTest(com.facebook.presto.sql.planner.assertions.BasePlanTest) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) Test(org.testng.annotations.Test) TpchTableLayoutHandle(com.facebook.presto.tpch.TpchTableLayoutHandle) TEST_SESSION(com.facebook.presto.SessionTestUtils.TEST_SESSION) ImmutableList(com.google.common.collect.ImmutableList) LOCAL(com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL) REPARTITION(com.facebook.presto.sql.planner.plan.ExchangeNode.Type.REPARTITION) FINAL(com.facebook.presto.spi.plan.AggregationNode.Step.FINAL) PlanBuilder(com.facebook.presto.sql.planner.iterative.rule.test.PlanBuilder) TableHandle(com.facebook.presto.spi.TableHandle) PARTIAL(com.facebook.presto.spi.plan.AggregationNode.Step.PARTIAL) BIGINT(com.facebook.presto.common.type.BigintType.BIGINT) ImmutableSet(com.google.common.collect.ImmutableSet) PlanNodeIdAllocator(com.facebook.presto.spi.plan.PlanNodeIdAllocator) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeClass(org.testng.annotations.BeforeClass) TestingTransactionHandle(com.facebook.presto.testing.TestingTransactionHandle) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) SqlParser(com.facebook.presto.sql.parser.SqlParser) REMOTE_STREAMING(com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.REMOTE_STREAMING) PlanNode(com.facebook.presto.spi.plan.PlanNode) TpchTableHandle(com.facebook.presto.tpch.TpchTableHandle) AggregationNode.groupingSets(com.facebook.presto.spi.plan.AggregationNode.groupingSets) TpchColumnHandle(com.facebook.presto.tpch.TpchColumnHandle) TableScanNode(com.facebook.presto.spi.plan.TableScanNode) Optional(java.util.Optional) ConnectorId(com.facebook.presto.spi.ConnectorId) Metadata(com.facebook.presto.metadata.Metadata) INNER(com.facebook.presto.sql.planner.plan.JoinNode.Type.INNER) PlanNode(com.facebook.presto.spi.plan.PlanNode) BasePlanTest(com.facebook.presto.sql.planner.assertions.BasePlanTest) Test(org.testng.annotations.Test)

Example 2 with LOCAL

use of com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL in project presto by prestodb.

the class RuntimeReorderJoinSides method apply.

@Override
public Result apply(JoinNode joinNode, Captures captures, Context context) {
    // Early exit if the leaves of the joinNode subtree include non tableScan nodes.
    if (searchFrom(joinNode, context.getLookup()).where(node -> node.getSources().isEmpty() && !(node instanceof TableScanNode)).matches()) {
        return Result.empty();
    }
    double leftOutputSizeInBytes = Double.NaN;
    double rightOutputSizeInBytes = Double.NaN;
    StatsProvider statsProvider = context.getStatsProvider();
    if (searchFrom(joinNode, context.getLookup()).where(node -> !(node instanceof TableScanNode) && !(node instanceof ExchangeNode)).findAll().size() == 1) {
        // Simple plan is characterized as Join directly on tableScanNodes only with exchangeNode in between.
        // For simple plans, directly fetch the overall table sizes as the size of the join sides to have
        // accurate input bytes statistics and meanwhile avoid non-negligible cost of collecting and processing
        // per-column statistics.
        leftOutputSizeInBytes = statsProvider.getStats(joinNode.getLeft()).getOutputSizeInBytes();
        rightOutputSizeInBytes = statsProvider.getStats(joinNode.getRight()).getOutputSizeInBytes();
    }
    if (Double.isNaN(leftOutputSizeInBytes) || Double.isNaN(rightOutputSizeInBytes)) {
        // Per-column estimate left and right output size for complex plans or when size statistics is unavailable.
        leftOutputSizeInBytes = statsProvider.getStats(joinNode.getLeft()).getOutputSizeInBytes(joinNode.getLeft().getOutputVariables());
        rightOutputSizeInBytes = statsProvider.getStats(joinNode.getRight()).getOutputSizeInBytes(joinNode.getRight().getOutputVariables());
    }
    if (Double.isNaN(leftOutputSizeInBytes) || Double.isNaN(rightOutputSizeInBytes)) {
        return Result.empty();
    }
    if (rightOutputSizeInBytes <= leftOutputSizeInBytes) {
        return Result.empty();
    }
    // Check if the swapped join is valid.
    if (!isSwappedJoinValid(joinNode)) {
        return Result.empty();
    }
    JoinNode swapped = joinNode.flipChildren();
    PlanNode newLeft = swapped.getLeft();
    Optional<VariableReferenceExpression> leftHashVariable = swapped.getLeftHashVariable();
    // Remove unnecessary LocalExchange in the current probe side. If the immediate left child (new probe side) of the join node
    // is a localExchange, there are two cases: an Exchange introduced by the current probe side (previous build side); or it is a UnionNode.
    // If the exchangeNode has more than 1 sources, it corresponds to the second case, otherwise it corresponds to the first case and could be safe to remove
    PlanNode resolvedSwappedLeft = context.getLookup().resolve(newLeft);
    if (resolvedSwappedLeft instanceof ExchangeNode && resolvedSwappedLeft.getSources().size() == 1) {
        // Ensure the new probe after skipping the local exchange will satisfy the required probe side property
        if (checkProbeSidePropertySatisfied(resolvedSwappedLeft.getSources().get(0), context)) {
            newLeft = resolvedSwappedLeft.getSources().get(0);
            // it as the leftHashVariable of the swapped join node.
            if (swapped.getLeftHashVariable().isPresent()) {
                int hashVariableIndex = resolvedSwappedLeft.getOutputVariables().indexOf(swapped.getLeftHashVariable().get());
                leftHashVariable = Optional.of(resolvedSwappedLeft.getSources().get(0).getOutputVariables().get(hashVariableIndex));
                // This is against typical iterativeOptimizer behavior and given this case is rare, just abort the swapping for this scenario.
                if (swapped.getOutputVariables().contains(swapped.getLeftHashVariable().get())) {
                    return Result.empty();
                }
            }
        }
    }
    // Add additional localExchange if the new build side does not satisfy the partitioning conditions.
    List<VariableReferenceExpression> buildJoinVariables = swapped.getCriteria().stream().map(JoinNode.EquiJoinClause::getRight).collect(toImmutableList());
    PlanNode newRight = swapped.getRight();
    if (!checkBuildSidePropertySatisfied(swapped.getRight(), buildJoinVariables, context)) {
        if (getTaskConcurrency(context.getSession()) > 1) {
            newRight = systemPartitionedExchange(context.getIdAllocator().getNextId(), LOCAL, swapped.getRight(), buildJoinVariables, swapped.getRightHashVariable());
        } else {
            newRight = gatheringExchange(context.getIdAllocator().getNextId(), LOCAL, swapped.getRight());
        }
    }
    JoinNode newJoinNode = new JoinNode(swapped.getSourceLocation(), swapped.getId(), swapped.getType(), newLeft, newRight, swapped.getCriteria(), swapped.getOutputVariables(), swapped.getFilter(), leftHashVariable, swapped.getRightHashVariable(), swapped.getDistributionType(), swapped.getDynamicFilters());
    log.debug(format("Probe size: %.2f is smaller than Build size: %.2f => invoke runtime join swapping on JoinNode ID: %s.", leftOutputSizeInBytes, rightOutputSizeInBytes, newJoinNode.getId()));
    return Result.ofPlanNode(newJoinNode);
}
Also used : ExchangeNode.systemPartitionedExchange(com.facebook.presto.sql.planner.plan.ExchangeNode.systemPartitionedExchange) Logger(com.facebook.airlift.log.Logger) StreamPropertyDerivations(com.facebook.presto.sql.planner.optimizations.StreamPropertyDerivations) Captures(com.facebook.presto.matching.Captures) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) StreamPreferredProperties.exactlyPartitionedOn(com.facebook.presto.sql.planner.optimizations.StreamPreferredProperties.exactlyPartitionedOn) Patterns.join(com.facebook.presto.sql.planner.plan.Patterns.join) Pattern(com.facebook.presto.matching.Pattern) StreamPreferredProperties.fixedParallelism(com.facebook.presto.sql.planner.optimizations.StreamPreferredProperties.fixedParallelism) LOCAL(com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL) Objects.requireNonNull(java.util.Objects.requireNonNull) SystemSessionProperties.isJoinSpillingEnabled(com.facebook.presto.SystemSessionProperties.isJoinSpillingEnabled) StreamPreferredProperties.singleStream(com.facebook.presto.sql.planner.optimizations.StreamPreferredProperties.singleStream) SystemSessionProperties.getTaskConcurrency(com.facebook.presto.SystemSessionProperties.getTaskConcurrency) PlanNodeSearcher.searchFrom(com.facebook.presto.sql.planner.optimizations.PlanNodeSearcher.searchFrom) ExchangeNode.gatheringExchange(com.facebook.presto.sql.planner.plan.ExchangeNode.gatheringExchange) JoinNode(com.facebook.presto.sql.planner.plan.JoinNode) Rule(com.facebook.presto.sql.planner.iterative.Rule) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) StatsProvider(com.facebook.presto.cost.StatsProvider) String.format(java.lang.String.format) SqlParser(com.facebook.presto.sql.parser.SqlParser) StreamPreferredProperties.defaultParallelism(com.facebook.presto.sql.planner.optimizations.StreamPreferredProperties.defaultParallelism) RIGHT(com.facebook.presto.sql.planner.plan.JoinNode.Type.RIGHT) SystemSessionProperties.isSpillEnabled(com.facebook.presto.SystemSessionProperties.isSpillEnabled) PlanNode(com.facebook.presto.spi.plan.PlanNode) List(java.util.List) REPLICATED(com.facebook.presto.sql.planner.plan.JoinNode.DistributionType.REPLICATED) LEFT(com.facebook.presto.sql.planner.plan.JoinNode.Type.LEFT) TableScanNode(com.facebook.presto.spi.plan.TableScanNode) StreamProperties(com.facebook.presto.sql.planner.optimizations.StreamPropertyDerivations.StreamProperties) StreamPreferredProperties(com.facebook.presto.sql.planner.optimizations.StreamPreferredProperties) Optional(java.util.Optional) PARTITIONED(com.facebook.presto.sql.planner.plan.JoinNode.DistributionType.PARTITIONED) Metadata(com.facebook.presto.metadata.Metadata) ExchangeNode(com.facebook.presto.sql.planner.plan.ExchangeNode) PlanNode(com.facebook.presto.spi.plan.PlanNode) TableScanNode(com.facebook.presto.spi.plan.TableScanNode) StatsProvider(com.facebook.presto.cost.StatsProvider) ExchangeNode(com.facebook.presto.sql.planner.plan.ExchangeNode) JoinNode(com.facebook.presto.sql.planner.plan.JoinNode) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression)

Example 3 with LOCAL

use of com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL in project presto by prestodb.

the class TestValidateAggregationsWithDefaultValues method testWithPartialAggregationBelowJoinWithoutSeparatingExchange.

@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Final aggregation with default value not separated from partial aggregation by local hash exchange")
public void testWithPartialAggregationBelowJoinWithoutSeparatingExchange() {
    PlanNode root = builder.aggregation(af -> af.step(FINAL).groupingSets(groupingSets(ImmutableList.of(variable), 2, ImmutableSet.of(0))).source(builder.join(INNER, builder.aggregation(ap -> ap.step(PARTIAL).groupingSets(groupingSets(ImmutableList.of(variable), 2, ImmutableSet.of(0))).source(tableScanNode)), builder.values())));
    validatePlan(root, true);
}
Also used : WarningCollector(com.facebook.presto.spi.WarningCollector) BasePlanTest(com.facebook.presto.sql.planner.assertions.BasePlanTest) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) Test(org.testng.annotations.Test) TpchTableLayoutHandle(com.facebook.presto.tpch.TpchTableLayoutHandle) TEST_SESSION(com.facebook.presto.SessionTestUtils.TEST_SESSION) ImmutableList(com.google.common.collect.ImmutableList) LOCAL(com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL) REPARTITION(com.facebook.presto.sql.planner.plan.ExchangeNode.Type.REPARTITION) FINAL(com.facebook.presto.spi.plan.AggregationNode.Step.FINAL) PlanBuilder(com.facebook.presto.sql.planner.iterative.rule.test.PlanBuilder) TableHandle(com.facebook.presto.spi.TableHandle) PARTIAL(com.facebook.presto.spi.plan.AggregationNode.Step.PARTIAL) BIGINT(com.facebook.presto.common.type.BigintType.BIGINT) ImmutableSet(com.google.common.collect.ImmutableSet) PlanNodeIdAllocator(com.facebook.presto.spi.plan.PlanNodeIdAllocator) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeClass(org.testng.annotations.BeforeClass) TestingTransactionHandle(com.facebook.presto.testing.TestingTransactionHandle) TupleDomain(com.facebook.presto.common.predicate.TupleDomain) SqlParser(com.facebook.presto.sql.parser.SqlParser) REMOTE_STREAMING(com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.REMOTE_STREAMING) PlanNode(com.facebook.presto.spi.plan.PlanNode) TpchTableHandle(com.facebook.presto.tpch.TpchTableHandle) AggregationNode.groupingSets(com.facebook.presto.spi.plan.AggregationNode.groupingSets) TpchColumnHandle(com.facebook.presto.tpch.TpchColumnHandle) TableScanNode(com.facebook.presto.spi.plan.TableScanNode) Optional(java.util.Optional) ConnectorId(com.facebook.presto.spi.ConnectorId) Metadata(com.facebook.presto.metadata.Metadata) INNER(com.facebook.presto.sql.planner.plan.JoinNode.Type.INNER) PlanNode(com.facebook.presto.spi.plan.PlanNode) BasePlanTest(com.facebook.presto.sql.planner.assertions.BasePlanTest) Test(org.testng.annotations.Test)

Aggregations

Metadata (com.facebook.presto.metadata.Metadata)3 PlanNode (com.facebook.presto.spi.plan.PlanNode)3 TableScanNode (com.facebook.presto.spi.plan.TableScanNode)3 VariableReferenceExpression (com.facebook.presto.spi.relation.VariableReferenceExpression)3 SqlParser (com.facebook.presto.sql.parser.SqlParser)3 LOCAL (com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.LOCAL)3 Optional (java.util.Optional)3 TEST_SESSION (com.facebook.presto.SessionTestUtils.TEST_SESSION)2 TupleDomain (com.facebook.presto.common.predicate.TupleDomain)2 BIGINT (com.facebook.presto.common.type.BigintType.BIGINT)2 ConnectorId (com.facebook.presto.spi.ConnectorId)2 TableHandle (com.facebook.presto.spi.TableHandle)2 WarningCollector (com.facebook.presto.spi.WarningCollector)2 FINAL (com.facebook.presto.spi.plan.AggregationNode.Step.FINAL)2 PARTIAL (com.facebook.presto.spi.plan.AggregationNode.Step.PARTIAL)2 AggregationNode.groupingSets (com.facebook.presto.spi.plan.AggregationNode.groupingSets)2 PlanNodeIdAllocator (com.facebook.presto.spi.plan.PlanNodeIdAllocator)2 BasePlanTest (com.facebook.presto.sql.planner.assertions.BasePlanTest)2 PlanBuilder (com.facebook.presto.sql.planner.iterative.rule.test.PlanBuilder)2 REMOTE_STREAMING (com.facebook.presto.sql.planner.plan.ExchangeNode.Scope.REMOTE_STREAMING)2