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

Use shorter aliases in CSE #10939

Merged
merged 15 commits into from
Jun 18, 2024
Merged

Use shorter aliases in CSE #10939

merged 15 commits into from
Jun 18, 2024

Conversation

peter-toth
Copy link
Contributor

@peter-toth peter-toth commented Jun 16, 2024

Which issue does this PR close?

Closes #10280.

Rationale for this change

This PR is based on @MohamedAbdeen21's #10868 and shortens aliases generated by CSE for readability.

What changes are included in this PR?

Use shorthand numeric aliases (__cse_1, __cse_2, ...) for common subexpressions.

Are these changes tested?

Yes, with existing and new UTs.

Are there any user-facing changes?

Yes, better and more concise logical plans.

@github-actions github-actions bot added optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt) labels Jun 16, 2024
@peter-toth peter-toth mentioned this pull request Jun 16, 2024
@peter-toth
Copy link
Contributor Author

cc @MohamedAbdeen21, @alamb

Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

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

Thank you @peter-toth -- I think this looks like a really nice improvement in readability.

I am going to run the planning benchmarks on this PR to see if it has any impact on performance, but even if not I think the readability improvements alone make it a valuable contribution

cc @waynexia as well

.expr_stats
.entry(expr_id.clone())
.or_insert((0, data_type));
let count = self.expr_stats.entry(expr_id.clone()).or_insert(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

it would be great to avoid this clone (which I think is a String) by using a slightly different API. Maybe something like

let count = if let Some(count) = self.expr_stats.get(expr_id) {
  count
} else {
  self.expr_stats.insert(expr_id.clone(), 0);
  0
};

Which while less elegant and requires hashing twice doens't clone the string 🤔

There may be a more clever way to avoid cloning the id

Also, I see the current code clones expr_id as well, so this change is no worse.

Copy link
Contributor Author

@peter-toth peter-toth Jun 17, 2024

Choose a reason for hiding this comment

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

The reason why I wouldn't change this in this PR is because my #10473 (https://github.com/apache/datafusion/pull/10473/files#diff-351499880963d6a383c92e156e75019cd9ce33107724a9635853d7d4cd1898d0R761) will completely eliminate string identifiers and remove these clones.

let expected = "Projection: UInt32(1) + test.a, UInt32(1) + {AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}} AS col1, UInt32(1) - {AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}} AS col2, {AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a)} AS AVG(UInt32(1) + test.a), UInt32(1) + {my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}} AS col3, UInt32(1) - {my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}} AS col4, {my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a)} AS my_agg(UInt32(1) + test.a)\
\n Aggregate: groupBy=[[{UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a]], aggr=[[AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}}) AS {AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}}, my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}}) AS {my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}})|{{UInt32(1) + test.a|{test.a}|{UInt32(1)}}}}, AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a) AS {AVG({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a)}, my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a) AS {my_agg({UInt32(1) + test.a|{test.a}|{UInt32(1)}} AS UInt32(1) + test.a)}]]\
\n Projection: UInt32(1) + test.a AS {UInt32(1) + test.a|{test.a}|{UInt32(1)}}, test.a, test.b, test.c\
let expected = "Projection: UInt32(1) + test.a, UInt32(1) + __cse_2 AS col1, UInt32(1) - __cse_2 AS col2, __cse_4 AS AVG(UInt32(1) + test.a), UInt32(1) + __cse_3 AS col3, UInt32(1) - __cse_3 AS col4, __cse_5 AS my_agg(UInt32(1) + test.a)\
Copy link
Contributor

Choose a reason for hiding this comment

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

That certainly looks much nicer

Comment on lines 89 to 90
/// A map that contains the common expressions extracted during the second, rewriting
/// traversal.
Copy link
Contributor

Choose a reason for hiding this comment

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

perhaps we can also update the docstring here to mention that the map contains the alias

Suggested change
/// A map that contains the common expressions extracted during the second, rewriting
/// traversal.
/// A map that contains the common expressions and their alias extracted during the second, rewriting
/// traversal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Fixed in be2e560 together with ExprStats docstring.

@alamb
Copy link
Contributor

alamb commented Jun 17, 2024

Running benchmarks now...

@alamb
Copy link
Contributor

alamb commented Jun 17, 2024

My benchmark runs show a small overall improvement (1% or so) so I feel like this PR is ready to go

I plan to leave this PR open for another day or so to allow @MohamedAbdeen21 to comment if the would like to

Benchmar Details

++ critcmp main cse-numeric-aliases
group                                         cse-numeric-aliases                    main
-----                                         -------------------                    ----
logical_aggregate_with_join                   1.00  1002.2±10.24µs        ? ?/sec    1.00  1004.2±16.91µs        ? ?/sec
logical_plan_tpcds_all                        1.00    152.6±0.87ms        ? ?/sec    1.01    153.5±1.09ms        ? ?/sec
logical_plan_tpch_all                         1.00     17.1±0.25ms        ? ?/sec    1.00     17.1±0.40ms        ? ?/sec
logical_select_all_from_1000                  1.00     18.6±1.50ms        ? ?/sec    1.02     19.0±0.12ms        ? ?/sec
logical_select_one_from_700                   1.01    816.1±5.13µs        ? ?/sec    1.00   811.0±10.48µs        ? ?/sec
logical_trivial_join_high_numbered_columns    1.00    765.1±8.39µs        ? ?/sec    1.00    764.9±7.57µs        ? ?/sec
logical_trivial_join_low_numbered_columns     1.00   752.6±12.80µs        ? ?/sec    1.00    753.8±7.02µs        ? ?/sec
physical_plan_tpcds_all                       1.00   1217.3±7.29ms        ? ?/sec    1.01   1223.9±6.30ms        ? ?/sec
physical_plan_tpch_all                        1.00     82.1±0.98ms        ? ?/sec    1.01     83.3±0.89ms        ? ?/sec
physical_plan_tpch_q1                         1.00      3.0±0.02ms        ? ?/sec    1.46      4.5±0.05ms        ? ?/sec
physical_plan_tpch_q10                        1.00      4.0±0.03ms        ? ?/sec    1.02      4.0±0.06ms        ? ?/sec
physical_plan_tpch_q11                        1.00      3.5±0.03ms        ? ?/sec    1.02      3.6±0.03ms        ? ?/sec
physical_plan_tpch_q12                        1.00      2.7±0.02ms        ? ?/sec    1.01      2.7±0.02ms        ? ?/sec
physical_plan_tpch_q13                        1.00      2.0±0.02ms        ? ?/sec    1.00      2.0±0.02ms        ? ?/sec
physical_plan_tpch_q14                        1.00      2.4±0.03ms        ? ?/sec    1.02      2.4±0.02ms        ? ?/sec
physical_plan_tpch_q16                        1.00      3.4±0.04ms        ? ?/sec    1.00      3.4±0.03ms        ? ?/sec
physical_plan_tpch_q17                        1.00      3.3±0.03ms        ? ?/sec    1.00      3.3±0.04ms        ? ?/sec
physical_plan_tpch_q18                        1.01      3.7±0.05ms        ? ?/sec    1.00      3.7±0.03ms        ? ?/sec
physical_plan_tpch_q19                        1.00      5.4±0.06ms        ? ?/sec    1.01      5.4±0.06ms        ? ?/sec
physical_plan_tpch_q2                         1.00      7.2±0.06ms        ? ?/sec    1.01      7.3±0.09ms        ? ?/sec
physical_plan_tpch_q20                        1.00      4.2±0.05ms        ? ?/sec    1.00      4.2±0.05ms        ? ?/sec
physical_plan_tpch_q21                        1.00      5.8±0.09ms        ? ?/sec    1.00      5.8±0.05ms        ? ?/sec
physical_plan_tpch_q22                        1.00      3.1±0.04ms        ? ?/sec    1.01      3.1±0.03ms        ? ?/sec
physical_plan_tpch_q3                         1.00      2.9±0.02ms        ? ?/sec    1.01      2.9±0.03ms        ? ?/sec
physical_plan_tpch_q4                         1.00      2.2±0.03ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_tpch_q5                         1.00      4.1±0.04ms        ? ?/sec    1.01      4.1±0.03ms        ? ?/sec
physical_plan_tpch_q6                         1.00  1423.8±19.83µs        ? ?/sec    1.01  1444.1±12.05µs        ? ?/sec
physical_plan_tpch_q7                         1.00      5.2±0.05ms        ? ?/sec    1.01      5.2±0.08ms        ? ?/sec
physical_plan_tpch_q8                         1.00      6.6±0.08ms        ? ?/sec    1.01      6.7±0.07ms        ? ?/sec
physical_plan_tpch_q9                         1.00      5.0±0.06ms        ? ?/sec    1.01      5.0±0.04ms        ? ?/sec
physical_select_all_from_1000                 1.00     58.9±0.28ms        ? ?/sec    1.04     61.4±0.36ms        ? ?/sec
physical_select_one_from_700                  1.01      3.6±0.02ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec

@MohamedAbdeen21
Copy link
Contributor

We did a thorough review of the changes in the old, now-closed, PR. FWIW, I'm happy with this change 👍 .

@waynexia
Copy link
Member

Looking great!

The CSE alias has changed many times, I think it's much closer to its final form now (I've skimmed #10473, and it also looks very 🆒!)

One thing I'd like to discuss is the prefix name. Unlike (#10868 (comment)) scalar, cse is an abbreviation and I'm not sure if it's that general and most users can figure out what it means. How about expanding it to something like common_expr to avoid potential confusion 🤔

@peter-toth
Copy link
Contributor Author

Sorry, I had rebase this PR. The commits remained the same as before, except the last one that changes the prefix to __common_expr: bfe814b

@alamb alamb merged commit 0c177d1 into apache:main Jun 18, 2024
23 checks passed
@alamb
Copy link
Contributor

alamb commented Jun 18, 2024

Thanks again @peter-toth @waynexia and @MohamedAbdeen21

@peter-toth
Copy link
Contributor Author

Thank you all for the review!

findepi pushed a commit to findepi/datafusion that referenced this pull request Jul 16, 2024
* initial change

* test renaming

* use counter instead of indexmap

* order slt tests

* change cse tests

* restore slt tests

* fix slt test

* formatting

* ensure no alias collision

* keep original alias numbers for collision

* ensure no collision in aggregate cse

* use `AliasGenerator` to generate aliases, use `__cse` prefix in common expression aliases, remove `DataType` from `ExprStats` as not needed, store aliases in `CommonExprs`, revert unnecessary changes

* use `into_values()` instead of `into_iter()` where possible

* fix docstring of `ExprStats` and `CommonExprs`

* use `__common_expr` prefix

---------

Co-authored-by: Mohamed Abdeen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make alias_symbol more human-readable
4 participants