feat: make StatisticsRegistry the default operator-statistics path#23651
feat: make StatisticsRegistry the default operator-statistics path#23651asolimando wants to merge 4 commits into
Conversation
|
Thank you for opening this pull request! Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch). Details |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #23651 +/- ##
=======================================
Coverage ? 80.66%
=======================================
Files ? 1087
Lines ? 367595
Branches ? 367595
=======================================
Hits ? 296535
Misses ? 53406
Partials ? 17654 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
1f2d39d to
38d5bb1
Compare
StatisticsContext (the single statistics walk, apache#23051) now consults the StatisticsRegistry (apache#21483) at each node before falling back to the operator's statistics_from_inputs, using the provider result's base Statistics. The registry is always-on: datafusion.optimizer.use_statistics_registry is deprecated and ignored (register providers on the SessionState instead). The now-redundant DefaultStatisticsProvider is deprecated, since the walk falls back natively.
The walk keeps core `Statistics` as its currency; a per-walk side cache carries provider `Extensions` separately, so a walk with no providers has no per-node overhead. A provider's `Computed` extensions are cached and reach parent-node providers as their `child_stats`; the built-in `statistics_from_inputs` fallback yields none, so extensions survive only across an unbroken chain of provider-handled nodes. Adds `StatisticsContext::compute_extended` (statistics + extensions) alongside `compute` (core statistics only). `StatisticsRegistry::compute` preserves extensions again; it and `compute_base` are deprecated in favor of `StatisticsContext`.
EXPLAIN ... show_statistics computed statistics with an empty registry, so registered providers were not reflected in the statistics column. Thread the session's StatisticsRegistry into the displayable plan; the column now reflects provider-supplied estimates when providers are registered, and is unchanged when none are.
A runnable example showing a StatisticsProvider that supplies and refines column statistics (post-filter distinct count via the survival formula) to flip a join's build side, with a before/after EXPLAIN.
38d5bb1 to
ded4292
Compare
| STORED AS PARQUET | ||
| LOCATION 'test_files/scratch/statistics_registry/dim_small.parquet'; | ||
|
|
||
| # -- Without registry -------------------------------------------------------- |
There was a problem hiding this comment.
Having removed use_statistics_registry config knob means the registry can't be turned off within an SLT. The no-provider path is covered by existing tests indirectly, and the with/without contrast now lives in the join_reorder example
| } | ||
| struct StatsCache { | ||
| statistics: HashMap<CacheKey, Arc<Statistics>>, | ||
| extensions: HashMap<CacheKey, Extensions>, |
There was a problem hiding this comment.
I kept https://github.com/apache/datafusion/pull/23651/changes#diff-149914d58cc354ddd4d84e283de4f8f07f3295b39137d850b3344448d4f6dc7a separated on purpose in case reviewers prefer to drop it from this PR.
The reason to have two caches is that caching on ExtendedStatistics at every node regressed the compute_statistics benchmark ~6% to 28% (median ~13%) on the no-provider path (a wrapper allocation per node).
The committed version keeps core Statistics in the walk and holds Extensions in a side map, populated only when a provider returns some. Benchmark parity when no providers are registered, extensions still reach parent-node providers.
I think this commit is worth keeping for feature parity w.r.t. StatisticsRegistry as existing today.
| metric_types: self.metric_types, | ||
| metric_categories: self.metric_categories, | ||
| format: self.format, | ||
| statistics_registry: self.statistics_registry, |
There was a problem hiding this comment.
The registry here is needed to keep EXPLAIN ANALYZE and EXPLAIN in sync when statistics providers are in use.
|
As discussed in #21122 (comment), making cc:
Note: the diff reads large (+1055 / -332), but ~620 of the added lines are examples and tests, ~38 are docs. The core change is ~400 lines, which goes down to a more reasonable ~300 if you exclude mechanical fixes. |
Which issue does this PR close?
Rationale for this change
#23051 unified statistics into one
StatisticsContextwalk. This folds thepreviously opt-in
StatisticsRegistry(#21483) into that walk as the default, soproviders are consulted inline and
use_statistics_registryis no longer needed.Consumed today by join ordering and EXPLAIN; more CBO rules are follow-up.
What changes are included in this PR?
StatisticsContextwalk (firstComputedwins, else
statistics_from_inputs); used byjoin_selection.use_statistics_registry(ignored, warns) andDefaultStatisticsProvider; add partition-awareStatisticsProvider::compute_statistics_with_args.Extensionsthrough the walk via a side cache (no costwithout providers); add
StatisticsContext::compute_extended, deprecateStatisticsRegistry::compute/compute_base.show_statisticsnow reflect the session registry.join_reorderexample.Are these changes tested?
Unit tests,
statistics_registry.slt, the example, the full extended suite, andcompute_statisticsat benchmark parity.Are there any user-facing changes?
use_statistics_registrydeprecated and ignored (default behavior unchanged).StatisticsRegistry::compute/compute_basedeprecated (55.0.0) forStatisticsContext;compute_extendedadded;DefaultStatisticsProviderdeprecated. Nothing removed. See the 55.0.0 upgrade guide.
Disclaimer: I used AI to assist in the code generation, I have manually reviewed the output and it matches my intention and understanding.