Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor](Nerieds) Refactor aggregate function/plan/rules and support related cbo rules #14827

Merged
merged 59 commits into from
Dec 18, 2022

Conversation

924060929
Copy link
Contributor

@924060929 924060929 commented Dec 5, 2022

Proposed changes

refactor

  • add AggregateExpression to shield the difference of AggregateFunction before disassemble and after
  • request GATHER physicalProperties for query, because query always collect result to the coordinator, use GATHER maybe select a better plan
  • refactor NormalizeAggregate
  • remove some physical fields for the LogicalAggregate, like AggPhase, isDisassemble
  • remove AggregateDisassemble and DistinctAggregateDisassemble, and use AggregateStrategies to generate various of PhysicalHashAggregate, like two phases aggregate, three phases aggregate, and cascades can auto select the lowest cost alternative.
  • move PushAggregateToOlapScan to AggregateStrategies
  • separate the traverse and visit method in FoldConstantRuleOnFE
    • if some expression not implement the visit method, the traverse method can handle and rewrite the children by default
    • if some expression implement the visit, the user defined traverse(invoke accept/visit method) will quickly return because the default visit method will not forward to the children, and the pre-process in traverse method will not be skipped.

new feature

  • support disable_nereids_rules to skip some rules.

example:

  1. create 1 bucket table n
CREATE TABLE `n` (
  `id` bigint(20) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(`id`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory" = "false",
"storage_format" = "V2",
"disable_auto_compaction" = "false"
);
  1. insert some rows into n
insert into n select * from numbers('number'='20000000')
  1. query table n
SET enable_nereids_planner=true;
SET enable_vectorized_engine=true;
SET enable_fallback_to_original_planner=false;
explain plan select id from n group by id;

the result show that we use the one stage aggregate

| PhysicalHashAggregate ( aggPhase=LOCAL, aggMode=INPUT_TO_RESULT, groupByExpr=[id#0], outputExpr=[id#0], partitionExpr=Optional.empty, requestProperties=[GATHER], stats=(rows=1, width=1, penalty=2.0E7) ) |
| +--PhysicalProject ( projects=[id#0], stats=(rows=20000000, width=1, penalty=0.0) )                                                                                                                                                                                                |
|    +--PhysicalOlapScan ( qualified=default_cluster:test.n, output=[id#0, name#1], stats=(rows=20000000, width=1, penalty=0.0) )                                                                                                                                                    |
  1. disable one stage aggregate
explain plan select
  /*+SET_VAR(disable_nereids_rules=DISASSEMBLE_ONE_PHASE_AGGREGATE_WITHOUT_DISTINCT)*/
  id
from n
group by id

the result is two stage aggregate

| PhysicalHashAggregate ( aggPhase=GLOBAL, aggMode=BUFFER_TO_RESULT, groupByExpr=[id#0], outputExpr=[id#0], partitionExpr=Optional[[id#0]], requestProperties=[GATHER], stats=(rows=1, width=1, penalty=2.0E7) ) |
| +--PhysicalHashAggregate ( aggPhase=LOCAL, aggMode=INPUT_TO_BUFFER, groupByExpr=[id#0], outputExpr=[id#0], partitionExpr=Optional[[id#0]], requestProperties=[ANY], stats=(rows=1, width=1, penalty=2.0E7) )     |
|    +--PhysicalProject ( projects=[id#0], stats=(rows=20000000, width=1, penalty=0.0) )                                                                                                                                                                                                   |
|       +--PhysicalOlapScan ( qualified=default_cluster:test.n, output=[id#0, name#1], stats=(rows=20000000, width=1, penalty=0.0) )                                                                                                                                                       |

Checklist(Required)

  1. Does it affect the original behavior:
    • Yes
    • No
    • I don't know
  2. Has unit tests been added:
    • Yes
    • No
    • No Need
  3. Has document been added or modified:
    • Yes
    • No
    • No Need
  4. Does it need to update dependencies:
    • Yes
    • No
  5. Are there any changes that cannot be rolled back:
    • Yes (If Yes, please explain WHY)
    • No

@github-actions github-actions bot added area/nereids area/planner Issues or PRs related to the query planner kind/test labels Dec 5, 2022
@924060929 924060929 marked this pull request as draft December 5, 2022 10:31
@hello-stephen
Copy link
Contributor

hello-stephen commented Dec 5, 2022

TeamCity pipeline, clickbench performance test result:
the sum of best hot time: 34.81 seconds
load time: 724 seconds
storage size: 17123497756 Bytes
https://doris-community-test-1308700295.cos.ap-hongkong.myqcloud.com/tmp/20221218045050_clickbench_pr_64696.html

@924060929 924060929 force-pushed the refactor-agg branch 2 times, most recently from 4f1a2be to 0ed25f3 Compare December 9, 2022 10:33
@924060929 924060929 marked this pull request as ready for review December 9, 2022 10:33
@924060929 924060929 force-pushed the refactor-agg branch 5 times, most recently from 67dc73e to ea3e000 Compare December 12, 2022 15:33
@924060929 924060929 changed the title (Refactor) (Nerieds) Refactor aggregate function/plan/rules and support related cbo rules [Refactor] (Nerieds) Refactor aggregate function/plan/rules and support related cbo rules Dec 13, 2022
@924060929 924060929 changed the title [Refactor] (Nerieds) Refactor aggregate function/plan/rules and support related cbo rules [Refactor](Nerieds) Refactor aggregate function/plan/rules and support related cbo rules Dec 13, 2022
@@ -314,6 +320,11 @@ public CascadesContext getCascadesContext() {
return cascadesContext;
}

public static PhysicalProperties buildInitRequireProperties(Plan initPlan) {
boolean isQuery = !(initPlan instanceof Command) || (initPlan instanceof ExplainCommand);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add (initPlan instanceof ExplainCommand)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently, explain command only for explain query, so we should require gather for it.
when the explain command support other sqls, like insert into, we should change it.

@@ -667,7 +668,8 @@ public String toString() {
builder.append(group).append("\n");
builder.append(" stats=").append(group.getStatistics()).append("\n");
StatsDeriveResult stats = group.getStatistics();
if (stats != null && group.getLogicalExpressions().get(0).getPlan() instanceof LogicalOlapScan) {
if (stats != null && !group.getLogicalExpressions().isEmpty()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is because, some group has no logical expression?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bingo

Comment on lines +225 to +227
if (!olapScan.getTable().isColocateTable() && olapScan.getScanTabletNum() == 1) {
return PhysicalProperties.GATHER;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a todo, let's find a better way to handle both tablet num == 1 and colocate table together in future

Comment on lines +65 to +67
return expr;
} else if (expr instanceof AggregateExpression && ((AggregateExpression) expr).getFunction().isDistinct()) {
return expr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why their child could not be fold?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe erase some distinct columns, that will be some bug

Comment on lines 106 to 114
public final Expression originExpr;
public final Slot remainExpr;
public final NamedExpression pushedExpr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add a example to explain them


return root;
// push expression to bottom project
Set<Alias> existsAliases = ExpressionUtils.collect(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it solve the problem of explosion of data? SQL like:

SELECT a + 1, a + 2, a + 3, SUM(b) FROM t GROUP BY a + 1, a + 2, a + 3;
SELECT a, SUM(b + 1), SUM(b + 2), SUM(b + 3) FROM t GROUP BY a;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the result is

LogicalAggregate(groupBy=(slot#1, slot#2, slot#3), output=[slot#1, slot#2, slot#3, sum(slot#4)])
                  |
LogicalProject(projects=[(a + 1)#1, (a + 2)#2, (a + 3)#3, b#4])

and

LogicalAggregate(groupBy=(slot#0), output=[slot#0, sum(slot#1), sum(slot#2), sum(slot#3)])
                  |
LogicalProject(projects=[a#0, (b + 1)#1, (b + 2)#2, (b + 3)#3])

*/
private List<PhysicalHashAggregate<Plan>> onePhaseAggregateWithoutDistinct(
LogicalAggregate<? extends Plan> logicalAgg, ConnectContext connectContext) {
RequireProperties requireGather = RequireProperties.of(PhysicalProperties.GATHER);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gather require could be a static member of RequireProperties

Copy link
Contributor Author

@924060929 924060929 Dec 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RequireProperties has a List<PhysicalProperties> properties match to every require physical properties of children.
so RequireProperties.GATHER is only used for one child and not very general

@924060929 924060929 force-pushed the refactor-agg branch 2 times, most recently from d2b5625 to 0989b92 Compare December 17, 2022 14:02
@github-actions github-actions bot added the approved Indicates a PR has been approved by one committer. label Dec 18, 2022
@github-actions
Copy link
Contributor

PR approved by at least one committer and no changes requested.

@github-actions
Copy link
Contributor

PR approved by anyone and no changes requested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by one committer. area/nereids area/planner Issues or PRs related to the query planner kind/test reviewed
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants