Skip to content

Statistics for nested columns - #9775

Open
thorfour wants to merge 4 commits into
vortex-data:developfrom
polarsignals:statistices-nested-columns
Open

thorfour wants to merge 4 commits into
vortex-data:developfrom
polarsignals:statistices-nested-columns

Conversation

@thorfour

@thorfour thorfour commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Being able to perform file level pruning on nested columns speeds up queries.

Changes

Adds post order stats to the file stats footer for nested columns. It adds a new is_nested: bool = false to the stats set flatbuffer for backward compatibility.

Additionally it modifies the way the stats footer is accumulated to use the same AggRef functions that the zone maps use as well.

Only goofy thing it it also has to track truncatable stats separately because the aggregate partials don't have a way to express exactness.

@codspeed

codspeed Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 2 benchmarks

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 2 regressed benchmarks
✅ 2172 untouched benchmarks
⏩ 534 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Simulation sum_i64 194.2 µs 224.8 µs -13.62%
❌ Simulation sum_v2_i64 195.1 µs 225.8 µs -13.59%
⚡ Simulation copy_nullable[16384] 424.2 µs 313.2 µs +35.46%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing polarsignals:statistices-nested-columns (cf42ed6) with develop (881b867)

Open in CodSpeed

Footnotes

  1. 534 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@robert3005

Copy link
Copy Markdown
Contributor

I think for maximum compatibility this has to be a new top level field in https://github.com/vortex-data/vortex/pull/9775/changes#diff-9c5a36ce8f55480706984e8996f192cd3abbdd1b97afa6f702f646b3ce42e039L25. The problem you run into is that old readers already shipped code that make assumption about existing footer statistics. One issue is that they validate field count and if the count doesn't add up they will assume it's a corrupted file. The writer could optionally populate both of the segments and the new version will only ever read the new field.

If you go that route you will see all the places that make assumptions about field stats that need fixing, i.e. datafusion, duckdb and jni

@joseph-isaacs

Copy link
Copy Markdown
Contributor

We also want to use aggregate partials here?

@thorfour
thorfour force-pushed the statistices-nested-columns branch from e24266f to 9c91f1a Compare September 17, 2026 12:53
@thorfour

Copy link
Copy Markdown
Contributor Author

@joseph-isaacs I've modified the summary stats to use aggregate partials.
@robert3005 I've moved the stats to a new top-level field, and left the legacy stats behavior. The writer can opt out of writing the legacy stats.

@thorfour
thorfour force-pushed the statistices-nested-columns branch from 9c91f1a to 3b07ff7 Compare September 17, 2026 12:56
@thorfour thorfour changed the title Statistices nested columns Statistics for nested columns Sep 17, 2026
Comment thread vortex-array/src/stats/mod.rs Outdated
Comment thread vortex-array/src/stats/mod.rs Outdated
Comment thread vortex-layout/src/layouts/file_stats.rs Outdated
Comment thread vortex-layout/src/layouts/file_stats.rs Outdated
Comment thread vortex-duckdb/src/copy.rs Outdated
Comment thread vortex-duckdb/src/file_reader.rs Outdated
Comment thread vortex-layout/src/layouts/file_stats.rs
Comment thread vortex-layout/src/layouts/file_stats.rs
@thorfour
thorfour force-pushed the statistices-nested-columns branch from 9f6ce2f to 83660ba Compare September 18, 2026 17:26
Comment thread vortex-file/flatbuffers/vortex-file/footer.fbs Outdated
Comment thread vortex-layout/src/layouts/file_stats.rs Outdated
Comment thread vortex-layout/src/layouts/file_stats.rs Outdated
Comment thread vortex-duckdb/src/copy.rs
@thorfour
thorfour force-pushed the statistices-nested-columns branch from e72a792 to ee01b02 Compare September 30, 2026 18:56
@thorfour
thorfour force-pushed the statistices-nested-columns branch from 6a3a2a8 to f8e7cf0 Compare October 1, 2026 20:22
@joseph-isaacs joseph-isaacs added the changelog/feature A new feature label Oct 6, 2026
Comment thread vortex-file/flatbuffers/vortex-file/footer.fbs
@joseph-isaacs joseph-isaacs added the action/bench-all Runs all CPU benchmarks. Do not combine with other benchmark labels; GPU is the only exception. label Oct 6, 2026
@thorfour
thorfour force-pushed the statistices-nested-columns branch 4 times, most recently from 9c210b1 to e0a709b Compare October 7, 2026 16:29
Comment thread vortex-duckdb/cpp/include/table_function.h Outdated
Comment thread vortex-duckdb/cpp/copy_function.cpp Outdated
Comment on lines +70 to +73
Exact(Scalar),
/// An upper bound of the true maximum, either because the maximum was truncated or because
/// it was combined from a serialized partial, which doesn't record exactness.
Inexact(Scalar),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we pull this out into a different pr

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you want to base this on a new exactness tracking PR, or do you want to drop this for now and always read back string min/max as approximate?

Comment thread vortex-duckdb/src/copy.rs Outdated
Comment on lines +173 to +179
fn partial_can_satisfy(
&self,
options: &Self::Options,
_partial: &Self::Partial,
requested: &AggregateFnRef,
) -> AggregateFnSatisfaction {
self.can_satisfy(options, requested)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

again

Comment thread vortex-duckdb/src/copy.rs

@myrrc myrrc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Duckdb changes look good to me, left some comments

Store file-level statistics via a post-order walk of the DType tree, so
nested struct fields get whole-file pruning instead of only top-level
columns. Each leaf gets a stats entry, and each nullable struct gets a
trailing null-count entry. A new `is_nested` footer flag keeps old files
readable via the legacy top-level-only layout.

Signed-off-by: "Thor" <thor.hansen@dash0.com>
Signed-off-by: Thor <thor.hansen@dash0.com>
Signed-off-by: Thor <thor.hansen@dash0.com>
Signed-off-by: Thor <thor.hansen@dash0.com>
Comment thread vortex-file/src/writer.rs
/// length against the number of top-level struct fields; omitting it means those readers find
/// no usable statistics in this file (though they can still read the data). Only use this if
/// you control every reader of the resulting files and don't need that compatibility.
pub fn exclude_legacy_statistics(mut self) -> Self {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We have a backcompat problem - when this is set the old readers will fail the read since they assert that the stats fields have the same length as the dtype. So we still need to make sure that holds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This defaults to true which shouldn't create a backwards compatibility issue though right? It's only for newer writers/readers that one would enable this option to not write the old stats. Or is the intent that we always will write the old stats to always support old readers?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You don't need to write the old stats, you just need the number of entries in the old stats set to be equal to top level field count. Thus even if you enable this option the file would be readable by old readers just without any statistics - right now it just errors

@thorfour
thorfour force-pushed the statistices-nested-columns branch 2 times, most recently from 5fd9add to ccf038e Compare October 8, 2026 17:01

@robert3005 robert3005 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One thing that we have to do here is to ban any file stats for dtypes that have structural nullability so we cannot allow stats for nullable lists and structs all the way through since those stats would be wrong right now. We need to fix propagation of nulls through structural types before they're allowed

Signed-off-by: Thor <thor.hansen@dash0.com>
@thorfour
thorfour force-pushed the statistices-nested-columns branch from ccf038e to cf42ed6 Compare October 8, 2026 17:20
@thorfour

thorfour commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

One thing that we have to do here is to ban any file stats for dtypes that have structural nullability so we cannot allow stats for nullable lists and structs all the way through since those stats would be wrong right now. We need to fix propagation of nulls through structural types before they're allowed

I didn't realize stats were broken for nullable nested types. I think to support this we'd need to change the footer to support marking leaves as skipped. Which could open up an api to allow users to specify per-columns stats (or not recording stats at all for certain columns). Or we can leave it as is and just wait for the fix of nulls in structural types to land first. wdyt?

We can implement this by having skipped fields point to empty AggregateSets. Is there an issue I can write in the comments for the code to skip those fields? Looks like #9205 covers it

@robert3005

Copy link
Copy Markdown
Contributor

Right now we have https://github.com/vortex-data/vortex/blob/develop/vortex-layout/src/layouts/file_stats.rs#L468-L471. For non nullable Structs things are correct but at the moment vortex allows you to have parent nullability different from child which needs either changing or adding handling for

@thorfour

thorfour commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

I'm on PTO next week, will pick this back up after vacation

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action/bench-all Runs all CPU benchmarks. Do not combine with other benchmark labels; GPU is the only exception. changelog/feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants