-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Fix Partial AggregateExec correctness issue dropping rows #18712
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
Conversation
| // Check if we should switch to skip aggregation mode | ||
| // It's important that we do this before we early emit since we've | ||
| // already updated the probe. | ||
| if let Some(new_state) = self.switch_to_skip_aggregation()? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unclear to me why we set update_skip_aggregation_probe here https://github.com/apache/datafusion/pull/18712/files#diff-69c8ecaca5e2c7005f2ed1facaa41f80b45bfd006f2357e53ff3072f535c287dL687 and not next to switch_to_skip_aggregation. I can't fully give an explanation yet but allowing the probe to be updated and then allowing the look to break before we get here seems dangerous? It's important that we emit everything before we move to the SkipAggregation state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@korowa does that make sense to you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read this new logic carefully and I think moving the set to switch aggregation state next to the check makes a lot of sense to me
b28fce0 to
353b11b
Compare
90d5a48 to
febdd78
Compare
|
|
||
| ExecutionState::Done => { | ||
| // Sanity check: all groups should have been emitted by now | ||
| if !self.group_values.is_empty() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding some protection here to try and avoid bugs like this happening in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather fail the query than return the wrong / incomplete results.
|
|
||
| // Create constrained memory to trigger early emission but not completely fail | ||
| let runtime = RuntimeEnvBuilder::default() | ||
| .with_memory_limit(1024, 1.0) // 100KB - enough to start but will trigger pressure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1024 bytes != 100KB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, I was playing around with this to repro the bug
|
Thank you for this PR @xanderbailey -- I plan to review it tomorrow |
alamb
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @xanderbailey -- this is an amazing find and a really well done PR. It was clear, and easy to read and makes sense to me.
Thank you
| // Check if we should switch to skip aggregation mode | ||
| // It's important that we do this before we early emit since we've | ||
| // already updated the probe. | ||
| if let Some(new_state) = self.switch_to_skip_aggregation()? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read this new logic carefully and I think moving the set to switch aggregation state next to the check makes a lot of sense to me
| use std::sync::Arc; | ||
|
|
||
| #[tokio::test] | ||
| async fn test_double_emission_race_condition_bug() -> Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I verified that this test covers the code in this PR as it fails without the code changes:
thread 'aggregates::row_hash::tests::test_double_emission_race_condition_bug' (41064140) panicked at datafusion/physical-plan/src/aggregates/row_hash.rs:1354:9:
assertion `left == right` failed: Unexpected number of groups
left: 100
right: 1124
stack backtrace:
|
I also added this ticket to the potential content of a datafusion 51.1.0 release: |
|
Thanks again @xanderbailey |
Which issue does this PR close?
More detail is in the issue.
Rationale for this change
This is a pretty major correctness issue.
What changes are included in this PR?
Fixes issue and reorders skip aggregate and emit early within partial aggregate execution
Are these changes tested?
Yes, the unit test that's added here previously failed before this change.
Are there any user-facing changes?