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

Add fetch to SortPreservingMergeExec and SortPreservingMergeStream #6811

Merged
merged 17 commits into from
Jul 3, 2023

Conversation

Dandandan
Copy link
Contributor

@Dandandan Dandandan commented Jun 30, 2023

Which issue does this PR close?

Closes #6000

Rationale for this change

Without fetch in SortPreserveMergeExec and in streaming_merge (which is used in SortExec) we effectively don't use the fetch anymore in sort besides limiting the amount of rows in batches.

This used to work before, as the fetch was also used to exit early whenever the limit has been reached.

No regressions in the sort bench:

merge sorted i64        time:   [3.2411 ms 3.2432 ms 3.2455 ms]
                        change: [-2.8398% -2.5245% -2.2191%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

sort merge i64          time:   [3.2955 ms 3.2982 ms 3.3011 ms]
                        change: [+0.0590% +0.1679% +0.2765%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe

sort i64                time:   [2.5579 ms 2.5640 ms 2.5706 ms]
                        change: [+1.0753% +1.3895% +1.7017%] (p = 0.00 < 0.05)
                        Performance has regressed.
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe

sort partitioned i64    time:   [311.35 µs 319.57 µs 329.25 µs]
                        change: [-15.453% -6.2902% +3.6954%] (p = 0.20 > 0.05)
                        No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

merge sorted f64        time:   [3.4235 ms 3.4289 ms 3.4345 ms]
                        change: [-23.917% -23.738% -23.569%] (p = 0.00 < 0.05)
                        Performance has improved.

sort merge f64          time:   [3.6465 ms 3.6548 ms 3.6632 ms]
                        change: [-0.8371% -0.4788% -0.1167%] (p = 0.01 < 0.05)
                        Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

sort f64                time:   [2.8972 ms 2.9107 ms 2.9255 ms]
                        change: [+0.6216% +1.0997% +1.6475%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 15 outliers among 100 measurements (15.00%)
  5 (5.00%) high mild
  10 (10.00%) high severe

sort partitioned f64    time:   [551.26 µs 575.34 µs 596.64 µs]
                        change: [-16.994% -12.798% -7.8668%] (p = 0.00 < 0.05)
                        Performance has improved.

merge sorted utf8 low cardinality
                        time:   [4.5004 ms 4.5365 ms 4.5716 ms]
                        change: [-2.2502% -1.1090% +0.0299%] (p = 0.06 > 0.05)
                        No change in performance detected.
Found 5 outliers among 100 measurements (5.00%)
  5 (5.00%) low mild

sort merge utf8 low cardinality
                        time:   [4.6399 ms 4.6529 ms 4.6664 ms]
                        change: [-0.7571% -0.3702% +0.0244%] (p = 0.07 > 0.05)
                        No change in performance detected.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

sort utf8 low cardinality
                        time:   [7.7734 ms 7.8037 ms 7.8349 ms]
                        change: [+0.0379% +0.6441% +1.2610%] (p = 0.04 < 0.05)
                        Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild

sort partitioned utf8 low cardinality
                        time:   [610.17 µs 620.22 µs 629.99 µs]
                        change: [-8.4099% -4.5155% -0.5342%] (p = 0.03 < 0.05)
                        Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high severe

merge sorted utf8 high cardinality
                        time:   [6.1074 ms 6.1243 ms 6.1419 ms]
                        change: [-1.0381% -0.5589% -0.1230%] (p = 0.02 < 0.05)
                        Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

sort merge utf8 high cardinality
                        time:   [6.6814 ms 6.6983 ms 6.7158 ms]
                        change: [-2.5717% -2.2253% -1.8896%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high mild

sort utf8 high cardinality
                        time:   [8.1829 ms 8.1994 ms 8.2162 ms]
                        change: [-0.4173% -0.0757% +0.2622%] (p = 0.66 > 0.05)
                        No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

sort partitioned utf8 high cardinality
                        time:   [644.47 µs 649.65 µs 654.47 µs]
                        change: [-13.125% -11.095% -9.1030%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
  4 (4.00%) low mild
  2 (2.00%) high mild
  3 (3.00%) high severe

merge sorted utf8 tuple time:   [11.723 ms 11.786 ms 11.848 ms]
                        change: [-2.0241% -1.2574% -0.4289%] (p = 0.00 < 0.05)
                        Change within noise threshold.

sort merge utf8 tuple   time:   [13.188 ms 13.243 ms 13.299 ms]
                        change: [-1.8995% -1.2794% -0.6598%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) low mild
  1 (1.00%) high mild

sort utf8 tuple         time:   [14.198 ms 14.247 ms 14.296 ms]
                        change: [-0.8779% -0.3814% +0.1117%] (p = 0.13 > 0.05)
                        No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Benchmarking sort partitioned utf8 tuple: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 6.0s, enable flat sampling, or reduce sample count to 60.
sort partitioned utf8 tuple
                        time:   [1.2378 ms 1.2471 ms 1.2566 ms]
                        change: [-9.2732% -7.8127% -6.3509%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) low severe
  1 (1.00%) high mild
  2 (2.00%) high severe

merge sorted utf8 dictionary
                        time:   [2.9129 ms 2.9210 ms 2.9294 ms]
                        change: [+0.0797% +0.5179% +0.9137%] (p = 0.01 < 0.05)
                        Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

sort merge utf8 dictionary
                        time:   [3.9508 ms 3.9738 ms 3.9968 ms]
                        change: [-6.4245% -5.5939% -4.7945%] (p = 0.00 < 0.05)
                        Performance has improved.

Benchmarking sort utf8 dictionary: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.5s, enable flat sampling, or reduce sample count to 50.
sort utf8 dictionary    time:   [1.4784 ms 1.4847 ms 1.4919 ms]
                        change: [-6.2917% -4.9163% -3.7280%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe

sort partitioned utf8 dictionary
                        time:   [984.87 µs 1.0000 ms 1.0149 ms]
                        change: [-13.857% -11.787% -9.6566%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  4 (4.00%) low mild
  1 (1.00%) high mild
  1 (1.00%) high severe

merge sorted utf8 dictionary tuple
                        time:   [4.8256 ms 4.8332 ms 4.8415 ms]
                        change: [-16.539% -6.4680% -0.2553%] (p = 0.22 > 0.05)
                        No change in performance detected.
Found 11 outliers among 100 measurements (11.00%)
  10 (10.00%) high mild
  1 (1.00%) high severe

sort merge utf8 dictionary tuple
                        time:   [6.0269 ms 6.4717 ms 7.3259 ms]
                        change: [-2.9171% +4.3031% +18.294%] (p = 0.68 > 0.05)
                        No change in performance detected.
Found 9 outliers among 100 measurements (9.00%)
  4 (4.00%) high mild
  5 (5.00%) high severe

sort utf8 dictionary tuple
                        time:   [8.1419 ms 8.1520 ms 8.1622 ms]
                        change: [-0.3065% -0.1314% +0.0523%] (p = 0.16 > 0.05)
                        No change in performance detected.

sort partitioned utf8 dictionary tuple
                        time:   [901.86 µs 915.45 µs 928.87 µs]
                        change: [-9.8500% -7.1963% -4.6576%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe

merge sorted mixed dictionary tuple
                        time:   [9.0339 ms 9.0583 ms 9.0833 ms]
                        change: [+0.3116% +0.7028% +1.0938%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

sort merge mixed dictionary tuple
                        time:   [10.596 ms 10.645 ms 10.695 ms]
                        change: [-1.5544% -0.8718% -0.1985%] (p = 0.01 < 0.05)
                        Change within noise threshold.
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe

sort mixed dictionary tuple
                        time:   [11.405 ms 11.443 ms 11.482 ms]
                        change: [-0.6486% -0.1840% +0.2809%] (p = 0.45 > 0.05)
                        No change in performance detected.

sort partitioned mixed dictionary tuple
                        time:   [1.9959 ms 2.0164 ms 2.0388 ms]
                        change: [-8.9630% -7.0896% -5.2999%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  6 (6.00%) high mild
  1 (1.00%) high severe

merge sorted mixed tuple
                        time:   [12.274 ms 12.392 ms 12.506 ms]
                        change: [-3.3147% -2.0286% -0.7903%] (p = 0.00 < 0.05)
                        Change within noise threshold.
Found 11 outliers among 100 measurements (11.00%)
  11 (11.00%) low mild

sort merge mixed tuple  time:   [13.243 ms 13.334 ms 13.425 ms]
                        change: [-2.9911% -2.1541% -1.3555%] (p = 0.00 < 0.05)
                        Performance has improved.

sort mixed tuple        time:   [12.588 ms 12.657 ms 12.725 ms]
                        change: [-1.1122% -0.3647% +0.3571%] (p = 0.35 > 0.05)
                        No change in performance detected.

sort partitioned mixed tuple
                        time:   [901.84 µs 923.93 µs 943.71 µs]
                        change: [-6.0896% -3.2873% -0.0848%] (p = 0.04 < 0.05)
                        Change within noise threshold.
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild

What changes are included in this PR?

Are these changes tested?

Covered by existing tests

Are there any user-facing changes?

@github-actions github-actions bot added the core Core DataFusion crate label Jun 30, 2023
Daniël Heres added 3 commits June 30, 2023 16:31
@Dandandan Dandandan changed the title Add fetch to sort preserving merge exec Add fetch to sort SortPreservingMergeExec Jun 30, 2023
@Dandandan Dandandan changed the title Add fetch to sort SortPreservingMergeExec Add fetch to sort SortPreservingMergeExec and SortPreservingMergeStream Jun 30, 2023
Daniël Heres added 2 commits June 30, 2023 16:54
@github-actions github-actions bot added the sqllogictest SQL Logic Tests (.slt) label Jun 30, 2023
@Dandandan Dandandan marked this pull request as ready for review July 1, 2023 10:58
@ozankabak ozankabak requested a review from mustafasrepo July 1, 2023 18:38
streaming_merge(
streams,
self.schema.clone(),
&self.expr,
metrics,
self.batch_size,
self.fetch,
Copy link
Contributor Author

@Dandandan Dandandan Jul 1, 2023

Choose a reason for hiding this comment

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

This was removed a few months ago to use streaming_merge in SortExec causing SortExec to spill even with a (low) fetch.

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.

I reviewed this carefully -- thank you @Dandandan .

I think it is worth considering adding fetch to the fuzz test cases in https://github.com/apache/arrow-datafusion/blob/main/datafusion/core/tests/fuzz_cases/merge_fuzz.rs to add some additional test coverage

@tustvold could you give this quick review for any issues?

cc @jychen7 who filed #6000

@@ -285,14 +286,13 @@ impl ExternalSorter {
})
.collect::<Result<_>>()?;

// TODO: Pushdown fetch to streaming merge (#6000)
Copy link
Contributor

Choose a reason for hiding this comment

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

🎉

@@ -67,7 +67,7 @@ Limit: skip=0, fetch=10
------------------TableScan: supplier projection=[s_suppkey, s_comment], partial_filters=[supplier.s_comment LIKE Utf8("%Customer%Complaints%")]
physical_plan
GlobalLimitExec: skip=0, fetch=10
--SortPreservingMergeExec: [supplier_cnt@3 DESC,p_brand@0 ASC NULLS LAST,p_type@1 ASC NULLS LAST,p_size@2 ASC NULLS LAST]
--SortPreservingMergeExec: [supplier_cnt@3 DESC,p_brand@0 ASC NULLS LAST,p_type@1 ASC NULLS LAST,p_size@2 ASC NULLS LAST], fetch=10
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@@ -227,11 +239,21 @@ impl<C: Cursor> SortPreservingMergeStream<C> {
if self.advance(stream_idx) {
self.loser_tree_adjusted = false;
self.in_progress.push_row(stream_idx);
if self.in_progress.len() < self.batch_size {

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 the hot path for SortPreservingMerge -- I suspect adding an extra check for fetch won't impact performance in any measurable way, but it might be worth while checking the benchmarks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense, otherwise we could maybe need two separate implementations (with/without fetch)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As benchmarks showed no significant difference, I kept this check in the hot path.

Copy link
Contributor

@jychen7 jychen7 left a comment

Choose a reason for hiding this comment

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

a small comment, otherwise LGTM.

@Dandandan Dandandan changed the title Add fetch to sort SortPreservingMergeExec and SortPreservingMergeStream Add fetch to SortPreservingMergeExec and SortPreservingMergeStream Jul 2, 2023
Copy link
Contributor

@mustafasrepo mustafasrepo left a comment

Choose a reason for hiding this comment

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

I have left some inline comments, other than these, this PR is LGTM!. Thanks @Dandandan for this PR.

@Dandandan Dandandan merged commit 727b6ff into main Jul 3, 2023
@alamb
Copy link
Contributor

alamb commented Jul 3, 2023

Thanks everyone -- this looks like it was a great team effort 👍

@alamb alamb deleted the add_fetch_to_sort_preserving_merge_exec branch July 3, 2023 19:06
2010YOUY01 pushed a commit to 2010YOUY01/arrow-datafusion that referenced this pull request Jul 5, 2023
apache#6811)

* Add fetch to sortpreservingmergeexec

* Add fetch to sortpreservingmergeexec

* fmt

* Deserialize

* Fmt

* Fix test

* Fix test

* Fix test

* Fix plan output

* Doc

* Update datafusion/core/src/physical_plan/sorts/sort_preserving_merge.rs

Co-authored-by: Andrew Lamb <[email protected]>

* Extract into method

* Remove from sort enforcement

* Update datafusion/core/src/physical_plan/sorts/merge.rs

Co-authored-by: Mustafa Akur <[email protected]>

* Update datafusion/proto/src/physical_plan/mod.rs

Co-authored-by: Mustafa Akur <[email protected]>

---------

Co-authored-by: Daniël Heres <[email protected]>
Co-authored-by: Andrew Lamb <[email protected]>
Co-authored-by: Mustafa Akur <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Core DataFusion crate sqllogictest SQL Logic Tests (.slt)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Push down limit to SortPreservingMergeExec and SortPreservingMergeStream
5 participants