Skip to content

Commit 1bdf135

Browse files
committed
Prune plan scans with zoned statistics
Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent a8c35cb commit 1bdf135

13 files changed

Lines changed: 834 additions & 100 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vortex-layout/src/layouts/zoned/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,11 @@ impl ZonedLayout {
358358
}
359359

360360
impl ZonedData {
361-
fn aggregate_fns(&self) -> Arc<[AggregateFnRef]> {
361+
pub(crate) fn zone_len(&self) -> usize {
362+
self.zone_len
363+
}
364+
365+
pub(crate) fn aggregate_fns(&self) -> Arc<[AggregateFnRef]> {
362366
match &self.zone_map_schema {
363367
ZoneMapSchema::LegacyStats(stats) => stats
364368
.iter()

vortex-layout/src/layouts/zoned/zone_map.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ use vortex_array::aggregate_fn::fns::all_null::AllNull;
1717
use vortex_array::aggregate_fn::fns::bounded_max::BOUNDED_MAX_BOUND;
1818
use vortex_array::aggregate_fn::fns::bounded_max::BoundedMax;
1919
use vortex_array::aggregate_fn::fns::nan_count::NanCount;
20+
use vortex_array::arrays::BoolArray;
2021
use vortex_array::arrays::ConstantArray;
2122
use vortex_array::arrays::PrimitiveArray;
2223
use vortex_array::arrays::StructArray;
2324
use vortex_array::arrays::struct_::StructArrayExt;
2425
use vortex_array::dtype::DType;
26+
use vortex_array::expr::BoundExpression;
2527
use vortex_array::expr::Expression;
2628
use vortex_array::expr::eq;
2729
use vortex_array::expr::get_item;
@@ -87,7 +89,7 @@ impl ZoneMap {
8789
Ok(unsafe { Self::new_unchecked(column_dtype, array, aggregate_fns, zone_len, row_count) })
8890
}
8991

90-
pub(super) unsafe fn new_unchecked(
92+
pub(crate) unsafe fn new_unchecked(
9193
column_dtype: DType,
9294
array: StructArray,
9395
aggregate_fns: Arc<[AggregateFnRef]>,
@@ -143,19 +145,34 @@ impl ZoneMap {
143145
/// only after the predicate has been lowered to the zone-map table.
144146
pub fn prune(&self, predicate: &Expression, session: &VortexSession) -> VortexResult<Mask> {
145147
let mut ctx = session.create_execution_ctx();
146-
let num_zones = self.array.len();
147-
let predicate = self.lower_stats(predicate.clone())?;
148+
self.applied_predicate(predicate)?
149+
.null_as_false()
150+
.execute(&mut ctx)
151+
}
148152

149-
let array = self.array.clone().into_array();
150-
let applied = array.apply(&predicate)?;
153+
/// Evaluate a pruning predicate while preserving unknown (null) proof values.
154+
pub(crate) fn evaluate(
155+
&self,
156+
predicate: &BoundExpression,
157+
session: &VortexSession,
158+
) -> VortexResult<BoolArray> {
159+
let mut ctx = session.create_execution_ctx();
160+
self.applied_predicate(&predicate.unbind())?
161+
.execute::<BoolArray>(&mut ctx)
162+
}
151163

152-
if !contains_row_count(&applied) {
153-
return applied.null_as_false().execute(&mut ctx);
154-
}
164+
fn applied_predicate(&self, predicate: &Expression) -> VortexResult<ArrayRef> {
165+
let num_zones = self.array.len();
166+
let predicate = self.lower_stats(predicate.clone())?;
155167

156-
let row_count_array = row_count_array(self.zone_len, self.row_count, num_zones)?;
157-
let substituted = substitute_row_count(applied, &row_count_array)?;
158-
substituted.null_as_false().execute(&mut ctx)
168+
let applied = self.array.clone().into_array().apply(&predicate)?;
169+
let applied = if contains_row_count(&applied) {
170+
let row_count_array = row_count_array(self.zone_len, self.row_count, num_zones)?;
171+
substitute_row_count(applied, &row_count_array)?
172+
} else {
173+
applied
174+
};
175+
Ok(applied)
159176
}
160177

161178
fn lower_stats(&self, predicate: Expression) -> VortexResult<Expression> {

vortex-layout/src/plan/display.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::fmt;
55

66
use super::ExpressionPlan;
77
use super::Plan;
8+
use super::ZonedPlan;
89

910
/// Context threaded through a plan tree traversal.
1011
pub struct PlanTreeContext {
@@ -110,7 +111,7 @@ impl PlanTreeExtractor for PlanSummaryExtractor {
110111
}
111112
}
112113

113-
/// Adds an expression annotation to [`ExpressionPlan`] nodes.
114+
/// Adds expression annotations to expression and zoned-pruning plans.
114115
pub struct PlanExpressionExtractor;
115116

116117
impl PlanTreeExtractor for PlanExpressionExtractor {
@@ -120,10 +121,16 @@ impl PlanTreeExtractor for PlanExpressionExtractor {
120121
_context: &PlanTreeContext,
121122
formatter: &mut fmt::Formatter<'_>,
122123
) -> fmt::Result {
123-
let Some(expression_plan) = plan.downcast_ref::<ExpressionPlan>() else {
124-
return Ok(());
125-
};
126-
write!(formatter, " expr={}", expression_plan.expression())
124+
if let Some(expression_plan) = plan.downcast_ref::<ExpressionPlan>() {
125+
return write!(formatter, " expr={}", expression_plan.expression());
126+
}
127+
if let Some(expression) = plan
128+
.downcast_ref::<ZonedPlan>()
129+
.and_then(ZonedPlan::pruning_expression)
130+
{
131+
return write!(formatter, " prune={expression}");
132+
}
133+
Ok(())
127134
}
128135
}
129136

vortex-layout/src/plan/optimizer/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ use super::DictPlan;
1616
use super::PlanRef;
1717
use super::RowIdxPlan;
1818
use super::StructPlan;
19+
use super::ZonedPlan;
1920
use super::plans::ExpressionChunkedRule;
2021
use super::plans::ExpressionDictRule;
2122
use super::plans::ExpressionRowIdxRule;
2223
use super::plans::ExpressionStructRule;
24+
use super::plans::ExpressionZonedRule;
2325

2426
static EXPRESSION_CHUNKED_RULE: PlanParentReduceRuleAdapter<ChunkedPlan, ExpressionChunkedRule> =
2527
PlanParentReduceRuleAdapter::new(ExpressionChunkedRule);
@@ -29,12 +31,15 @@ static EXPRESSION_ROW_IDX_RULE: PlanParentReduceRuleAdapter<RowIdxPlan, Expressi
2931
PlanParentReduceRuleAdapter::new(ExpressionRowIdxRule);
3032
static EXPRESSION_STRUCT_RULE: PlanParentReduceRuleAdapter<StructPlan, ExpressionStructRule> =
3133
PlanParentReduceRuleAdapter::new(ExpressionStructRule);
34+
static EXPRESSION_ZONED_RULE: PlanParentReduceRuleAdapter<ZonedPlan, ExpressionZonedRule> =
35+
PlanParentReduceRuleAdapter::new(ExpressionZonedRule);
3236

3337
static PARENT_RULES: PlanParentRuleSet = PlanParentRuleSet::new(&[
3438
&EXPRESSION_CHUNKED_RULE,
3539
&EXPRESSION_DICT_RULE,
3640
&EXPRESSION_ROW_IDX_RULE,
3741
&EXPRESSION_STRUCT_RULE,
42+
&EXPRESSION_ZONED_RULE,
3843
]);
3944

4045
/// Attempts a static rewrite for `parent` and its child at `child_idx`.

vortex-layout/src/plan/plans/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ pub use row_idx::RowIdxPlan;
2323
pub use row_idx::RowIdxValuesPlan;
2424
pub(crate) use struct_::ExpressionStructRule;
2525
pub use struct_::StructPlan;
26+
pub(crate) use zoned::ExpressionZonedRule;
2627
pub use zoned::ZonedPlan;

0 commit comments

Comments
 (0)