feat(querier): partition-level time pruning (RFC 0007) - #117
Conversation
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
Warning Review limit reached
More reviews will be available in 50 minutes and 55 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR implements hour-level partition pruning for time-windowed Parquet queries. A new ChangesHour partition pruning feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR implements RFC 0007’s deferred refinement: partition-level time pruning in the querier, allowing queries with a time window to skip entire year/month/day/hour partitions before DataFusion opens Parquet footers. This makes scanned row groups and bytes read track the query window rather than the corpus’s total time span.
Changes:
- Add
hour_partition_in_window(dir, start_ns, end_ns) -> boolinourios-parquetto conservatively decide whether anhour=HHpartition can overlap a half-open time window. - Update
ourios-querier’sresolve_live_filesto accept the querytime_rangeand skip out-of-window hour partitions when resolving live Parquet files. - Add integration + unit tests asserting directory-level pruning keeps DataFusion work flat as the corpus time span grows.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/ourios-querier/tests/execution.rs | Adds an integration test proving time-windowed queries prune entire out-of-window hour partitions before DataFusion sees them. |
| crates/ourios-querier/src/lib.rs | Threads time_range into live-file resolution and applies hour-partition overlap pruning prior to DataFusion execution. |
| crates/ourios-parquet/src/partition.rs | Implements conservative hour-partition/window overlap predicate + unit tests for boundary and fallback cases. |
| crates/ourios-parquet/src/lib.rs | Re-exports hour_partition_in_window for use by the querier. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The otel-demo run showed template-exact queries prune nothing on real logs —
a template recurs in every hour partition, so every row group's template_id
min/max matches and DataFusion scans them all (v4: 5/5 row groups). The
inverted-index-collapse locality needs the time-range predicate to skip whole
partitions, which the querier had deferred ("today the time bound is a column
predicate").
This implements it:
- `ourios-parquet`: `hour_partition_in_window(dir, start_ns, end_ns)` — does a
`…/hour=HH` leaf's [hour_start, +1h) UTC span overlap the window? It's
CONSERVATIVE: any unparseable/foreign path or non-instant returns true (do
not prune), so pruning can never drop in-window data.
- `ourios-querier`: `resolve_live_files` takes the query's time range and skips
a leaf partition's files when the hour can't overlap — so DataFusion never
opens those footers. It layers on the `time_unix_nano` column predicate,
which stays the row-level correctness authority.
So a time-windowed query's scanned row groups track the window, not the
corpus's time span. New `rfc0007_2_time_window_prunes_whole_partitions` proves
it deterministically: the same in-window result over a 10× larger time span
(2 vs 20 filler hours) hands DataFusion the same tiny row-group set (the
out-of-window partitions are pruned at the directory level, never reaching the
engine). Plus unit tests for the overlap math + the conservative fallbacks.
Descent-level pruning (skipping whole year/month subtrees, not just leaves) is
a further optimisation; leaf pruning already removes the footer reads that
dominate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6d18d07 to
6e95dc2
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng (#118) The payoff of #117 (partition-level time pruning), measured on the real frozen otel-demo corpus. The existing unwindowed b2/otel-demo query scans every partition (a template recurs across all hours on real logs — v4: 5/5). A query bounded to the corpus's first hour now reaches DataFusion with only that hour's partition(s); the rest are pruned at the directory level, so the scanned work tracks the WINDOW, not the corpus span. - `BuiltStore` exposes `min/max_time_unix_nano` (the corpus's timestamp span) so the bench can pick a real window. - `b2/otel-demo` adds a `corpus-window-1h` arm: a query over [first hour) that probes + asserts ≥1 partition is pruned before DataFusion, logs the pruning, and benches the windowed latency. Skipped for single-partition corpora. Indicative on v4 (735,377 rows, 5 partitions; laptop, NOT §9): unwindowed: 5/5 row groups, 5.5 MB, 2.9 ms 1h window: 1 row group (4 partitions pruned), 267 KB, 1.3 ms → ~20× less data read, the inverted-index-collapse locality on real logs. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
What
Implements partition-level time pruning in the querier (RFC 0007's explicitly-deferred refinement) — directly motivated by the otel-demo run.
Why (the finding that drove it)
Running
b2/otel-demoon the real frozen corpus (#116) showed a template-exact query prunes nothing on real logs — v4 scanned 5/5 row groups. A template recurs in every hour partition, so every row group'stemplate_idmin/max matches the queried id. The inverted-index-collapse locality (B2's thesis) only materialises when a time-range predicate skips whole partitions before any footer is opened. The querier had this deferred ("today the time bound is a column predicate").How
ourios-parquet—hour_partition_in_window(dir, start_ns, end_ns) -> bool: does a…/year=…/month=…/day=…/hour=HHleaf's[hour_start, +1h)UTC span overlap the half-open window? Conservative by design: any unparseable/foreign path or non-instant returnstrue(do not prune), so pruning can never drop in-window data.ourios-querier—resolve_live_filesnow takes the query'stime_rangeand skips a leaf partition's files when its hour can't overlap, so DataFusion never opens those footers. It layers on thetime_unix_nanocolumn predicate, which remains the row-level correctness authority — pruning is a pure optimisation.Result
A time-windowed query's scanned row groups track the window, not the corpus's time span — the missing piece for B2 on real logs.
Tests
rfc0007_2_time_window_prunes_whole_partitions(integration): the same in-window result over a 10× larger time span (2 vs 20 filler hours) hands DataFusion the same tiny row-group set — the out-of-window partitions are pruned at the directory level and never reach the engine (scanned + pruned <= 2, not 21). This is the deterministic analogue of the real-corpus B2 win.cargo fmt --all --check,cargo clippy --workspace --all-targets --all-features -D warnings,cargo test --workspaceall green.Invariants (CLAUDE.md §3.7, RFC0007.5 / §3.9)
Tenant isolation is untouched (resolution still rooted at the tenant dir). Pruning is conservative and never drops in-window data; the column predicate is unchanged, so row-level results are identical with or without pruning. Within RFC 0007's accepted scope (the doc anticipated this), not a new RFC.
Descent-level pruning (skipping whole year/month subtrees) is a further optimisation; leaf pruning already removes the footer reads that dominate.
Part of epic #82 (querier) / epic #81 (thesis-gate validation).
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests