Skip to content

feat[iceberg]: runtime statistics - #676

Merged
gabotechs merged 5 commits into
datafusion-contrib:iceberg-0.10from
sandugood:feat/add-planning-stats
Aug 26, 2026
Merged

feat[iceberg]: runtime statistics#676
gabotechs merged 5 commits into
datafusion-contrib:iceberg-0.10from
sandugood:feat/add-planning-stats

Conversation

@sandugood

@sandugood sandugood commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Tackles #608.

Added runtime statistics that can be extracted from the current snapshot metadata.

total-records and total-files-size which are being used in the partition_statistics function.

@sandugood
sandugood force-pushed the feat/add-planning-stats branch from 6af5a68 to 63bd029 Compare August 25, 2026 21:32
@sandugood

Copy link
Copy Markdown
Contributor Author

Seems like CI failure is not related to the current PR scope

@gabotechs gabotechs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @sandugood! looking very good.

Comment thread iceberg/src/data_source.rs Outdated
Ok(Arc::new(Statistics {
num_rows: Precision::Exact(num_rows),
total_byte_size: Precision::Exact(total_byte_size),
column_statistics: vec![],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the reason why the CI is failing (https://github.com/datafusion-contrib/datafusion-distributed/actions/runs/32901579585/job/97976700594?pr=676).

The schema might declare, for example, 3 columns, but here we are returning a column_statistics vec of 0 columns, and DataFusion, while propagating statistics to upstream nodes, will try to access index 0, 1 and 2 of this empty vec![].

It would be cool if we can actually get some per-column statistics. Do you think that would be possible?

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.

Fixed by returning ColumnStatistics::new_unknown() for each column of the projected schema. Per-column stats are possible from the manifest entries (null_value_counts, lower_bounds, upper_bounds per data file), but that needs async manifest reads cached at construction, so I'd propose doing it in a follow-up PR.

Comment thread iceberg/src/data_source.rs Outdated
Comment on lines +309 to +311
let Some(snap) = snapshot else {
return Ok(Arc::new(Statistics::new_unknown(schema)));
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So, if current snapshot is None, we get no statistics. This will be pretty bad, as these stats are essentially what will inform the distributed planner how much to distribute.

Is there any chance of getting the stats from somewhere else that we know it's always going to be present?

@sandugood sandugood Aug 26, 2026

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.

I have changed this piece of code and now populate everything with zeroes in that case.

Why do I think that this is correct? If the table was created, then we would have an entry for that table in the catalog (REST, Glue, HMS etc.). However, if no data files were committed means None for snapshot.

If table wasn't even created we would get error earlier, though.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤔 Yeap, your reasoning sounds right. I don't know enough about Iceberg but what you say makes sense, so let's stick to it.

If you happen to have a link to some docs explaining this, cool, otherwise, it's fine to leave it like this.

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.

https://iceberg.apache.org/spec/#table-metadata-fields
current-snapshot-id is an Optional parameter (for all v1-v4 of Iceberg)

Also I've tried to confirm it with a simple Iceberg table creation with Spark (without any data inserted)
After running DESCRIBE TABLE EXTENDED and checking metadata.json

tg_image_3160661423

Comment thread iceberg/src/data_source.rs Outdated

@gabotechs gabotechs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Amazing, great work @sandugood!

Comment on lines +80 to +81
let display = displayable(plan.as_ref())
.set_show_statistics(true)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice! I didn't now this was an option.

@gabotechs
gabotechs merged commit 1033447 into datafusion-contrib:iceberg-0.10 Aug 26, 2026
32 checks passed
@gabotechs

Copy link
Copy Markdown
Collaborator

A follow up to this one might be to have some nice per-column statistics, but that depends more on iceberg-rust capabilities for exposing that kind of information.

@gabotechs

Copy link
Copy Markdown
Collaborator

Added a comment in the original issue about this.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants