Repository navigation
perf: extend compact IN-list pruning to ordered types - #25012
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #25012 +/- ##
==========================================
+ Coverage 81.69% 81.73% +0.03%
==========================================
Files 1127 1129 +2
Lines 415386 417153 +1767
Branches 415386 417153 +1767
==========================================
+ Hits 339358 340948 +1590
- Misses 56093 56175 +82
- Partials 19935 20030 +95 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
kosiew
left a comment
There was a problem hiding this comment.
@kumarUjjawal, thanks for working on this. The compact sorted-domain approach looks like a nice extension of the existing string pruning optimization to ordered primitive, temporal, decimal, and binary types. I also appreciate the unit, Parquet integration, benchmark, and configuration coverage. I just have one non-blocking suggestion around end-to-end NULL coverage.
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn ordered_in_list_parquet_pruning() { |
There was a problem hiding this comment.
Could we add one nullable primitive or binary end-to-end case with a NULL member in the list? The unit tests cover the compact filter-only semantics well, but I think an integration case would also be useful to exercise the new Parquet source and full-match path and make sure a compact predicate with NULL does not accidentally bypass the row filter.
kosiew
left a comment
There was a problem hiding this comment.
Thanks for the follow-up. The new nullable Int64 case includes a NULL member in the list and verifies the full Parquet path, including row filtering, compact-predicate selection, limit behavior, and pruning metrics.
I also checked the follow-up diff and did not find any new issues beyond the previously reviewed changes.
Looks good to me. Thanks for taking care of this!
|
Thank you @kosiew as always for taking the time and wonderful reviews. |
## Which issue does this PR close? - Closes apache#24709 ## Rationale for this change Compact pruning for large `IN` lists only supports string columns. Other ordered types use one min/max comparison for each literal. Large lists create large expression trees and make pruning more expensive. These types can use the same compact sorted-domain approach. ## What changes are included in this PR? This PR adds compact `IN` and `NOT IN` pruning for: - Variable-length binary types - Signed and unsigned integers - Decimal types - Date and time types - Timestamp and duration types - Dictionary-encoded forms of these types String and binary values share the byte-domain implementation. Primitive types use typed contiguous arrays. The compact path preserves NULL behavior and dictionary value NULLs. Unsupported types keep the existing per-value fallback. Floating-point types remain unsupported because of NaN and signed zero. `FixedSizeBinary` and nested types also remain unsupported. The default `max_in_list_size` value remains 20. ### Benchmarks With 1,024 literals and 4,096 statistics containers: - String `IN` evaluation is 37.8x faster. - String `NOT IN` evaluation is 21.4x faster. - Int64 `IN` evaluation is 118x faster. - Int64 `NOT IN` evaluation is 111x faster. - Predicate construction is 15.9x to 32.1x faster. Commands: ```shell cargo bench -p datafusion-pruning --bench string_in_list_pruning cargo bench -p datafusion-pruning --bench primitive_in_list_pruning ``` ## What is the testing strategy for this PR? The tests cover: - All supported type families - Both `IN` and `NOT IN` - NULL-containing and all-NULL lists - Dictionary and run-end-encoded values - Missing, inverted, and truncated statistics - Parquet row-group and page pruning - Per-value fallback for unsupported types - Result equality between compact pruning and the original filter The following commands passed: ```shell cargo test -p datafusion-pruning cargo test -p datafusion --test parquet_integration string_in_list_pruning cargo test -p datafusion-sqllogictest --test sqllogictests -- information_schema cargo clippy -p datafusion-pruning -p datafusion --all-targets --all-features -- -D warnings cargo fmt --all -- --check ``` ## Are there any user-facing changes? Large `IN` and `NOT IN` lists can use compact pruning for more ordered types. This behavior applies when `datafusion.execution.parquet.max_in_list_size` is set above 20. The default value and SQL results do not change. This PR does not change public APIs. Backport provenance: - Upstream PR: apache#25012 - Upstream commit: f3f420b - Upstream self-tests and all additions/removals retained; only unavoidable fork patch context resolved. - Any fork-specific adaptation is kept in a separate following commit. Signed-off-by: discord9 <[email protected]>
Which issue does this PR close?
IN-list pruning beyond string types #24709Rationale for this change
Compact pruning for large
INlists only supports string columns.Other ordered types use one min/max comparison for each literal. Large lists create large expression trees and make pruning more expensive.
These types can use the same compact sorted-domain approach.
What changes are included in this PR?
This PR adds compact
INandNOT INpruning for:String and binary values share the byte-domain implementation. Primitive types use typed contiguous arrays.
The compact path preserves NULL behavior and dictionary value NULLs. Unsupported types keep the existing per-value fallback.
Floating-point types remain unsupported because of NaN and signed zero.
FixedSizeBinaryand nested types also remain unsupported.The default
max_in_list_sizevalue remains 20.Benchmarks
With 1,024 literals and 4,096 statistics containers:
INevaluation is 37.8x faster.NOT INevaluation is 21.4x faster.INevaluation is 118x faster.NOT INevaluation is 111x faster.Commands:
What is the testing strategy for this PR?
The tests cover:
INandNOT INThe following commands passed:
Are there any user-facing changes?
Large
INandNOT INlists can use compact pruning for more ordered types.This behavior applies when
datafusion.execution.parquet.max_in_list_sizeis set above 20. The default value and SQL results do not change.This PR does not change public APIs.