Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
github-actions[bot] commented on PR #22235: URL: https://github.com/apache/datafusion/pull/22235#issuecomment-5029451246 Thank you for your contribution. Unfortunately, this pull request is stale because it has been open 60 days with no activity. Please remove the stale label or comment or this will be closed in 7 days. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] - To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
asolimando commented on code in PR #22235:
URL: https://github.com/apache/datafusion/pull/22235#discussion_r3280521346
##
datafusion/datasource-parquet/src/page_filter.rs:
##
@@ -336,6 +410,190 @@ impl PagePruningAccessPlanFilter {
pub fn filter_number(&self) -> usize {
self.predicates.len()
}
+
+/// Like [`Self::prune_plan_with_page_index`] but also surfaces, as a
+/// side-effect of the pruning iteration that already runs, a
+/// per-conjunct accumulator with the rows that conjunct alone
+/// would have proven skippable. Callers use this to seed a
+/// per-FilterId selectivity prior without doing any extra pruning
+/// work — every page-index lookup that would have happened in
+/// `prune_plan_with_page_index` happens exactly once here too.
+pub fn prune_plan_with_per_conjunct_stats(
+&self,
+mut access_plan: ParquetAccessPlan,
+arrow_schema: &Schema,
+parquet_schema: &SchemaDescriptor,
+parquet_metadata: &ParquetMetaData,
+file_metrics: &ParquetFileMetrics,
+) -> (ParquetAccessPlan, Vec, usize) {
+// scoped timer updates on drop
+let _timer_guard = file_metrics.page_index_eval_time.timer();
+
+let mut per_conjunct: Vec =
(0..self.predicates.len())
+.map(|i| PerConjunctPageStats {
+tag: self.tags.as_ref().and_then(|t| t.get(i).copied()),
+rows_seen: 0,
+rows_skipped: 0,
+})
+.collect();
+
+if self.predicates.is_empty() {
+return (access_plan, per_conjunct, 0);
+}
+
+let groups = parquet_metadata.row_groups();
+if groups.is_empty() {
+return (access_plan, per_conjunct, 0);
+}
+
+if parquet_metadata.offset_index().is_none()
+|| parquet_metadata.column_index().is_none()
+{
+return (access_plan, per_conjunct, 0);
+}
+
+// Same accumulators as the untagged path, plus per-conjunct.
Review Comment:
The comment shows that you are aware of the duplication w.r.t. the untagged
path, is this a temporary state for the draft? (with draft PRs it's sometimes a
bit tricky to tell what is what, apologies if that should be evident at this
point)
##
datafusion/pruning/src/pruning_predicate.rs:
##
@@ -568,6 +697,50 @@ impl PruningPredicate {
Ok(builder.build())
}
+/// Like [`Self::prune`] but also returns per-conjunct pruning
+/// stats when this predicate was constructed via
+/// [`Self::try_new_tagged_conjuncts`]. The `Vec` is the same
+/// AND'd result `prune` would return; the per-conjunct stats are
+/// computed by evaluating each leaf sub-predicate against the same
+/// `statistics` and counting pruned/seen containers.
+///
+/// Returns `(prune_result, vec![])` for predicates constructed via
+/// the plain [`Self::try_new`] (no sub-predicates available).
+pub fn prune_per_conjunct(
+&self,
+statistics: &S,
+) -> Result<(Vec, Vec)> {
+let combined = self.prune(statistics)?;
+let Some(sub_predicates) = &self.sub_predicates else {
+return Ok((combined, Vec::new()));
+};
+
+let total_containers = statistics.num_containers();
+let mut per_conjunct: Vec =
+Vec::with_capacity(sub_predicates.len());
+for sub in sub_predicates {
+let kept = sub.predicate.prune(statistics)?;
Review Comment:
It seems that we are looping through the predicates twice, the second time
here, but IIUC we already do a full traversal at line 713, I wonder if we could
do both at the same time as this might be costly with many conjuncts/deep
expressions?
##
datafusion/pruning/src/pruning_predicate.rs:
##
@@ -499,9 +544,77 @@ impl PruningPredicate {
required_columns,
orig_expr: expr,
literal_guarantees,
+sub_predicates: None,
})
}
+/// Like [`Self::try_new`] but takes already-split top-level
+/// conjuncts each carrying a caller tag (typically a `FilterId`).
+/// Builds one [`PruningPredicate`] per conjunct as a leaf
+/// sub-predicate. The wrapper itself is a marker holding the
+/// leaves; calls to [`Self::prune`] AND the leaves' results,
+/// avoiding a redundant combined-predicate construction.
+/// [`Self::prune_per_conjunct`] also reads from the same leaves.
+///
+/// Conjuncts whose individual `try_new` would error or return
+/// always-true are silently skipped (their tags do not appear in
+/// the per-conjunct output).
+pub fn try_new_tagged_conjuncts(
+tagged: &[(usize, Arc)],
+schema: SchemaRef,
+) -> Result {
+// Build per-conjunct PruningPredicates (each is a leaf — i.e.
+// its own `sub_predicates` is `None`).
+let mut sub_predicates
Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
asolimando commented on PR #22235: URL: https://github.com/apache/datafusion/pull/22235#issuecomment-4466312804 > If you're willing to help review / get this in good shape for a review from a committer I think that would go a long way towards getting it across the line. I've mostly gotten it to work without paying too much attention to the API, interaction with existing methods, etc., hence why this is in draft. Sure, I will put it on my to-do list for next week when I am back from holidays! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] - To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
adriangb commented on PR #22235: URL: https://github.com/apache/datafusion/pull/22235#issuecomment-4466057458 If you're willing to help review / get this in good shape for a review from a committer I think that would go a long way towards getting it across the line. I've mostly gotten it to work without paying too much attention to the API, interaction with existing methods, etc., hence why this is in draft. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] - To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
asolimando commented on PR #22235: URL: https://github.com/apache/datafusion/pull/22235#issuecomment-4465657140 This would also be extremely useful for bootstrapping a cold stats in catalog via execution and runtime stats, I hope this feature lands! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] - To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
Re: [PR] Per-conjunct pruning statistics for PruningPredicate [datafusion]
github-actions[bot] commented on PR #22235: URL: https://github.com/apache/datafusion/pull/22235#issuecomment-4464067698 Thank you for opening this pull request! Reviewer note: [cargo-semver-checks](https://github.com/obi1kenobi/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 ``` Cloning apache/main Building datafusion-datasource-parquet v53.1.0 (current) Built [ 41.981s] (current) Parsing datafusion-datasource-parquet v53.1.0 (current) Parsed [ 0.029s] (current) Building datafusion-datasource-parquet v53.1.0 (baseline) Built [ 41.559s] (baseline) Parsing datafusion-datasource-parquet v53.1.0 (baseline) Parsed [ 0.028s] (baseline) Checking datafusion-datasource-parquet v53.1.0 -> v53.1.0 (no change; assume patch) Checked [ 0.189s] 222 checks: 222 pass, 30 skip Summary no semver update required Finished [ 85.520s] datafusion-datasource-parquet Building datafusion-physical-expr-common v53.1.0 (current) Built [ 19.150s] (current) Parsing datafusion-physical-expr-common v53.1.0 (current) Parsed [ 0.022s] (current) Building datafusion-physical-expr-common v53.1.0 (baseline) Built [ 18.963s] (baseline) Parsing datafusion-physical-expr-common v53.1.0 (baseline) Parsed [ 0.022s] (baseline) Checking datafusion-physical-expr-common v53.1.0 -> v53.1.0 (no change; assume patch) Checked [ 0.266s] 222 checks: 222 pass, 30 skip Summary no semver update required Finished [ 39.577s] datafusion-physical-expr-common Building datafusion-proto v53.1.0 (current) Built [ 52.530s] (current) Parsing datafusion-proto v53.1.0 (current) Parsed [ 0.142s] (current) Building datafusion-proto v53.1.0 (baseline) Built [ 53.624s] (baseline) Parsing datafusion-proto v53.1.0 (baseline) Parsed [ 0.147s] (baseline) Checking datafusion-proto v53.1.0 -> v53.1.0 (no change; assume patch) Checked [ 2.254s] 222 checks: 221 pass, 1 fail, 0 warn, 30 skip --- failure enum_variant_added: enum variant added on exhaustive enum --- Description: A publicly-visible enum without #[non_exhaustive] has a new variant. ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/enum_variant_added.ron Failed in: variant ExprType:OptionalFilter in /home/runner/work/datafusion/datafusion/datafusion/proto/src/generated/prost.rs:1397 variant ExprType:OptionalFilter in /home/runner/work/datafusion/datafusion/datafusion/proto/src/generated/prost.rs:1397 Summary semver requires new major version: 1 major and 0 minor checks failed Finished [ 111.070s] datafusion-proto Building datafusion-pruning v53.1.0 (current) Built [ 36.108s] (current) Parsing datafusion-pruning v53.1.0 (current) Parsed [ 0.013s] (current) Building datafusion-pruning v53.1.0 (baseline) Built [ 36.494s] (baseline) Parsing datafusion-pruning v53.1.0 (baseline) Parsed [ 0.013s] (baseline) Checking datafusion-pruning v53.1.0 -> v53.1.0 (no change; assume patch) Checked [ 0.102s] 222 checks: 222 pass, 30 skip Summary no semver update required Finished [ 74.652s] datafusion-pruning ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] - To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
