Search in sources :

Example 1 with PositionalOrderBy

use of io.crate.planner.PositionalOrderBy in project crate by crate.

the class NestedLoopJoin method build.

@Override
public ExecutionPlan build(PlannerContext plannerContext, Set<PlanHint> hints, ProjectionBuilder projectionBuilder, int limit, int offset, @Nullable OrderBy order, @Nullable Integer pageSizeHint, Row params, SubQueryResults subQueryResults) {
    /*
         * Benchmarks reveal that if rows are filtered out distributed execution gives better performance.
         * Therefore if `filterNeeded` is true (there is joinCondition or a filtering after the join operation)
         * then it's a good indication that distributed execution will be faster.
         *
         * We may at some point add some kind of session-settings to override this behaviour
         * or otherwise come up with a better heuristic.
         */
    Integer childPageSizeHint = !isFiltered && limit != TopN.NO_LIMIT ? limitAndOffset(limit, offset) : null;
    ExecutionPlan left = lhs.build(plannerContext, hints, projectionBuilder, NO_LIMIT, 0, null, childPageSizeHint, params, subQueryResults);
    ExecutionPlan right = rhs.build(plannerContext, hints, projectionBuilder, NO_LIMIT, 0, null, childPageSizeHint, params, subQueryResults);
    PositionalOrderBy orderByFromLeft = left.resultDescription().orderBy();
    boolean hasDocTables = baseTables.stream().anyMatch(r -> r instanceof DocTableRelation);
    boolean isDistributed = hasDocTables && isFiltered && !joinType.isOuter();
    LogicalPlan leftLogicalPlan = lhs;
    LogicalPlan rightLogicalPlan = rhs;
    isDistributed = isDistributed && (!left.resultDescription().nodeIds().isEmpty() && !right.resultDescription().nodeIds().isEmpty());
    boolean blockNlPossible = !isDistributed && isBlockNlPossible(left, right);
    JoinType joinType = this.joinType;
    if (!orderByWasPushedDown && joinType.supportsInversion() && (isDistributed && lhs.numExpectedRows() < rhs.numExpectedRows() && orderByFromLeft == null) || (blockNlPossible && lhs.numExpectedRows() > rhs.numExpectedRows())) {
        // 1) The right side is always broadcast-ed, so for performance reasons we switch the tables so that
        // the right table is the smaller (numOfRows). If left relation has a pushed-down OrderBy that needs
        // to be preserved, then the switch is not possible.
        // 2) For block nested loop, the left side should always be smaller. Benchmarks have shown that the
        // performance decreases if the left side is much larger and no limit is applied.
        ExecutionPlan tmpExecutionPlan = left;
        left = right;
        right = tmpExecutionPlan;
        leftLogicalPlan = rhs;
        rightLogicalPlan = lhs;
        joinType = joinType.invert();
    }
    Tuple<Collection<String>, List<MergePhase>> joinExecutionNodesAndMergePhases = configureExecution(left, right, plannerContext, isDistributed);
    List<Symbol> joinOutputs = Lists2.concat(leftLogicalPlan.outputs(), rightLogicalPlan.outputs());
    SubQueryAndParamBinder paramBinder = new SubQueryAndParamBinder(params, subQueryResults);
    Symbol joinInput = null;
    if (joinCondition != null) {
        joinInput = InputColumns.create(paramBinder.apply(joinCondition), joinOutputs);
    }
    NestedLoopPhase nlPhase = new NestedLoopPhase(plannerContext.jobId(), plannerContext.nextExecutionPhaseId(), isDistributed ? "distributed-nested-loop" : "nested-loop", Collections.singletonList(JoinOperations.createJoinProjection(outputs, joinOutputs)), joinExecutionNodesAndMergePhases.v2().get(0), joinExecutionNodesAndMergePhases.v2().get(1), leftLogicalPlan.outputs().size(), rightLogicalPlan.outputs().size(), joinExecutionNodesAndMergePhases.v1(), joinType, joinInput, Symbols.typeView(leftLogicalPlan.outputs()), leftLogicalPlan.estimatedRowSize(), leftLogicalPlan.numExpectedRows(), blockNlPossible);
    return new Join(nlPhase, left, right, TopN.NO_LIMIT, 0, TopN.NO_LIMIT, outputs.size(), orderByFromLeft);
}
Also used : SelectSymbol(io.crate.expression.symbol.SelectSymbol) Symbol(io.crate.expression.symbol.Symbol) JoinType(io.crate.planner.node.dql.join.JoinType) Join(io.crate.planner.node.dql.join.Join) PositionalOrderBy(io.crate.planner.PositionalOrderBy) ExecutionPlan(io.crate.planner.ExecutionPlan) DocTableRelation(io.crate.analyze.relations.DocTableRelation) Collection(java.util.Collection) List(java.util.List) NestedLoopPhase(io.crate.execution.dsl.phases.NestedLoopPhase)

Example 2 with PositionalOrderBy

use of io.crate.planner.PositionalOrderBy in project crate by crate.

the class GroupByPlannerTest method testNonDistributedGroupByOnClusteredColumnSortedScalar.

@Test
public void testNonDistributedGroupByOnClusteredColumnSortedScalar() throws Exception {
    var e = SQLExecutor.builder(clusterService, 2, RandomizedTest.getRandom(), List.of()).addTable(TableDefinitions.USER_TABLE_DEFINITION).build();
    Merge merge = e.plan("select count(*) + 1, id from users group by id order by count(*) + 1 limit 20");
    Collect collect = (Collect) merge.subPlan();
    RoutedCollectPhase collectPhase = ((RoutedCollectPhase) collect.collectPhase());
    assertThat(collectPhase.projections(), contains(instanceOf(GroupProjection.class), instanceOf(OrderedTopNProjection.class), instanceOf(EvalProjection.class)));
    assertThat(((OrderedTopNProjection) collectPhase.projections().get(1)).orderBy().size(), is(1));
    assertThat(collectPhase.projections().get(0).requiredGranularity(), is(RowGranularity.SHARD));
    MergePhase mergePhase = merge.mergePhase();
    assertThat(mergePhase.projections(), contains(instanceOf(TopNProjection.class)));
    PositionalOrderBy positionalOrderBy = mergePhase.orderByPositions();
    assertThat(positionalOrderBy, notNullValue());
    assertThat(positionalOrderBy.indices().length, is(1));
    assertThat(positionalOrderBy.indices()[0], is(0));
    assertThat(positionalOrderBy.reverseFlags()[0], is(false));
    assertThat(positionalOrderBy.nullsFirst()[0], is(false));
}
Also used : PositionalOrderBy(io.crate.planner.PositionalOrderBy) MergePhase(io.crate.execution.dsl.phases.MergePhase) Merge(io.crate.planner.Merge) Collect(io.crate.planner.node.dql.Collect) OrderedTopNProjection(io.crate.execution.dsl.projection.OrderedTopNProjection) RoutedCollectPhase(io.crate.execution.dsl.phases.RoutedCollectPhase) CrateDummyClusterServiceUnitTest(io.crate.test.integration.CrateDummyClusterServiceUnitTest) Test(org.junit.Test) RandomizedTest(com.carrotsearch.randomizedtesting.RandomizedTest)

Example 3 with PositionalOrderBy

use of io.crate.planner.PositionalOrderBy in project crate by crate.

the class GroupByPlannerTest method testNonDistributedGroupByOnClusteredColumnSorted.

@Test
public void testNonDistributedGroupByOnClusteredColumnSorted() throws Exception {
    var e = SQLExecutor.builder(clusterService, 2, RandomizedTest.getRandom(), List.of()).addTable(TableDefinitions.USER_TABLE_DEFINITION).build();
    Merge merge = e.plan("select count(*), id from users group by id order by 1 desc nulls last limit 20");
    Collect collect = ((Collect) merge.subPlan());
    RoutedCollectPhase collectPhase = ((RoutedCollectPhase) collect.collectPhase());
    List<Projection> collectProjections = collectPhase.projections();
    assertThat(collectProjections, contains(instanceOf(GroupProjection.class), instanceOf(OrderedTopNProjection.class), // swap id, count(*) -> count(*), id
    instanceOf(EvalProjection.class)));
    assertThat(collectProjections.get(1), instanceOf(OrderedTopNProjection.class));
    assertThat(((OrderedTopNProjection) collectProjections.get(1)).orderBy().size(), is(1));
    assertThat(collectProjections.get(0).requiredGranularity(), is(RowGranularity.SHARD));
    MergePhase mergePhase = merge.mergePhase();
    assertThat(mergePhase.projections(), contains(instanceOf(TopNProjection.class)));
    PositionalOrderBy positionalOrderBy = mergePhase.orderByPositions();
    assertThat(positionalOrderBy, notNullValue());
    assertThat(positionalOrderBy.indices().length, is(1));
    assertThat(positionalOrderBy.indices()[0], is(0));
    assertThat(positionalOrderBy.reverseFlags()[0], is(true));
    assertThat(positionalOrderBy.nullsFirst()[0], is(false));
}
Also used : PositionalOrderBy(io.crate.planner.PositionalOrderBy) MergePhase(io.crate.execution.dsl.phases.MergePhase) Merge(io.crate.planner.Merge) Collect(io.crate.planner.node.dql.Collect) OrderedTopNProjection(io.crate.execution.dsl.projection.OrderedTopNProjection) GroupProjection(io.crate.execution.dsl.projection.GroupProjection) FilterProjection(io.crate.execution.dsl.projection.FilterProjection) Projection(io.crate.execution.dsl.projection.Projection) TopNProjection(io.crate.execution.dsl.projection.TopNProjection) EvalProjection(io.crate.execution.dsl.projection.EvalProjection) OrderedTopNProjection(io.crate.execution.dsl.projection.OrderedTopNProjection) RoutedCollectPhase(io.crate.execution.dsl.phases.RoutedCollectPhase) CrateDummyClusterServiceUnitTest(io.crate.test.integration.CrateDummyClusterServiceUnitTest) Test(org.junit.Test) RandomizedTest(com.carrotsearch.randomizedtesting.RandomizedTest)

Example 4 with PositionalOrderBy

use of io.crate.planner.PositionalOrderBy in project crate by crate.

the class Eval method addEvalProjection.

private ExecutionPlan addEvalProjection(PlannerContext plannerContext, ExecutionPlan executionPlan, Row params, SubQueryResults subQueryResults) {
    PositionalOrderBy orderBy = executionPlan.resultDescription().orderBy();
    PositionalOrderBy newOrderBy = null;
    SubQueryAndParamBinder binder = new SubQueryAndParamBinder(params, subQueryResults);
    List<Symbol> boundOutputs = Lists2.map(outputs, binder);
    if (orderBy != null) {
        newOrderBy = orderBy.tryMapToNewOutputs(source.outputs(), boundOutputs);
        if (newOrderBy == null) {
            executionPlan = Merge.ensureOnHandler(executionPlan, plannerContext);
        }
    }
    InputColumns.SourceSymbols ctx = new InputColumns.SourceSymbols(Lists2.map(source.outputs(), binder));
    executionPlan.addProjection(new EvalProjection(InputColumns.create(boundOutputs, ctx)), executionPlan.resultDescription().limit(), executionPlan.resultDescription().offset(), newOrderBy);
    return executionPlan;
}
Also used : PositionalOrderBy(io.crate.planner.PositionalOrderBy) InputColumns(io.crate.execution.dsl.projection.builder.InputColumns) EvalProjection(io.crate.execution.dsl.projection.EvalProjection) Symbol(io.crate.expression.symbol.Symbol)

Example 5 with PositionalOrderBy

use of io.crate.planner.PositionalOrderBy in project crate by crate.

the class Order method build.

@Override
public ExecutionPlan build(PlannerContext plannerContext, Set<PlanHint> planHints, ProjectionBuilder projectionBuilder, int limit, int offset, @Nullable OrderBy order, @Nullable Integer pageSizeHint, Row params, SubQueryResults subQueryResults) {
    ExecutionPlan plan = source.build(plannerContext, planHints, projectionBuilder, limit, offset, orderBy, pageSizeHint, params, subQueryResults);
    if (plan.resultDescription().orderBy() != null) {
        // Collect applied ORDER BY eagerly to produce a optimized execution plan;
        if (source instanceof Collect) {
            return plan;
        }
    }
    if (plan.resultDescription().hasRemainingLimitOrOffset()) {
        plan = Merge.ensureOnHandler(plan, plannerContext);
    }
    InputColumns.SourceSymbols ctx = new InputColumns.SourceSymbols(source.outputs());
    List<Symbol> orderByInputColumns = InputColumns.create(this.orderBy.orderBySymbols(), ctx);
    ensureOrderByColumnsArePresentInOutputs(orderByInputColumns);
    OrderedTopNProjection topNProjection = new OrderedTopNProjection(Limit.limitAndOffset(limit, offset), 0, InputColumns.create(outputs, ctx), orderByInputColumns, this.orderBy.reverseFlags(), this.orderBy.nullsFirst());
    PositionalOrderBy positionalOrderBy = PositionalOrderBy.of(this.orderBy, outputs);
    plan.addProjection(topNProjection, limit, offset, positionalOrderBy);
    return plan;
}
Also used : InputColumns(io.crate.execution.dsl.projection.builder.InputColumns) PositionalOrderBy(io.crate.planner.PositionalOrderBy) ExecutionPlan(io.crate.planner.ExecutionPlan) Symbol(io.crate.expression.symbol.Symbol) OrderedTopNProjection(io.crate.execution.dsl.projection.OrderedTopNProjection)

Aggregations

PositionalOrderBy (io.crate.planner.PositionalOrderBy)6 OrderedTopNProjection (io.crate.execution.dsl.projection.OrderedTopNProjection)3 Symbol (io.crate.expression.symbol.Symbol)3 Test (org.junit.Test)3 RandomizedTest (com.carrotsearch.randomizedtesting.RandomizedTest)2 MergePhase (io.crate.execution.dsl.phases.MergePhase)2 RoutedCollectPhase (io.crate.execution.dsl.phases.RoutedCollectPhase)2 EvalProjection (io.crate.execution.dsl.projection.EvalProjection)2 InputColumns (io.crate.execution.dsl.projection.builder.InputColumns)2 ExecutionPlan (io.crate.planner.ExecutionPlan)2 Merge (io.crate.planner.Merge)2 Collect (io.crate.planner.node.dql.Collect)2 CrateDummyClusterServiceUnitTest (io.crate.test.integration.CrateDummyClusterServiceUnitTest)2 OrderBy (io.crate.analyze.OrderBy)1 DocTableRelation (io.crate.analyze.relations.DocTableRelation)1 RowAccountingWithEstimatorsTest (io.crate.breaker.RowAccountingWithEstimatorsTest)1 Row (io.crate.data.Row)1 NestedLoopPhase (io.crate.execution.dsl.phases.NestedLoopPhase)1 FilterProjection (io.crate.execution.dsl.projection.FilterProjection)1 GroupProjection (io.crate.execution.dsl.projection.GroupProjection)1