perf(filtered-read): prune non-candidate fragment metadata - #8587
Conversation
|
Addressed in 4e4207f. Stable-ID routing now carries the loaded RowIdSequence and computed upper offset ranges into LoadedFragment; Exact and Refined/AtMost planning reuse them, while AtLeast still maps its lower bound once. I added a deterministic regression that counts mask_to_offset_ranges spans (4 candidate fragments produce 4 calls; the previous head produced 8). On the 2,600-fragment cache-hot dense workload, median plan latency improved from 8.26 ms at 824551d to 7.15 ms at the current head (1.15x); the main control was 6.40 ms and the measured phase performed 0 S3 reads. The PR body now includes the methodology and exact-current-head S3 results. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ Gate recommendation: approve.
The re-requested revision preserves the bounded stable-ID routing budget with a standard compare-exchange loop. It removes the nightly atomic API warning without changing candidate pruning, the 16 MiB retention bound, or fallback recomputation.
Problem
After a scalar index returns its row-ID mask,
FilteredReadExec::get_or_create_plan_implstill loads deletion vectors, row counts, and row-ID metadata for every fragment before applying that mask. An exact index miss therefore performs an O(fragment count) metadata pass even though no fragment can contribute a row.This is a follow-up to #7792. That PR removed the second all-fragment metadata load during stream construction; the first planning-time pass remained. Related to #4189, which tracks broader filtered-read planning costs.
Change
Use the index result's upper bound to decide whether a fragment can contribute before loading its full metadata:
only_indexed_fragmentsis enabled;Candidate fragments still load and apply their deletion vectors, so stale deleted index hits remain excluded. Pruning uses the upper bound of refined index results to avoid false negatives.
Benchmark
Lower is better for every metric below.
e958adfdf)150e000f0)The review follow-up also measures cache-hot dense stable-row-ID planning, where all 5,200 physical row IDs route to all 2,600 fragments:
824551d44)150e000f0)The main-branch control was 7.13 ms/plan. The current implementation is 0.72 ms/plan (1.10x) above that control because it performs the stable-ID routing pass needed for pruning, but it no longer repeats the same mapping during final planning. All cache-hot measured plans performed 0 S3 reads.
Environment and methodology:
m7i.4xlargeinus-east-1a, reading S3 in the same region.org_idandrepo_id.release-with-debug,--no-default-features --features aws; their SHA256 hashes were checked before measurement.Session; the table reports medians.IOTrackerstatistics after open.Measured bytes followed the same pattern: exact-empty planning dropped from 1,814,800 B/query to 0 B/query; the zero-hit query dropped from 1,882,874 B/query to 68,074 B/query; the one-hit query dropped from 1,965,927 B/query to 151,825 B/query.
Correctness and limitations
The regression coverage includes stable and address-style row IDs, exact-empty and sparse non-empty masks, refined upper bounds, partially indexed datasets, and
only_indexed_fragmentsbehavior. A deterministic dense stable-ID test countsmask_to_offset_rangesspans: four candidate fragments must produce exactly four mappings; the pre-follow-up implementation produced eight. A separate boundary test verifies that retained range payload cannot exceed the per-plan budget.For a non-empty stable row-ID mask, this change still visits each covered fragment's row-ID sequence to discover candidate fragments. The benchmark fixture stores those sequences inline, so it removes the S3 deletion-vector/row-count reads but not the O(fragment count) routing walk. Datasets with external row-ID metadata can still perform O(fragment count) row-ID metadata reads. Eliminating that remaining cost requires carrying physical candidate-fragment information from scalar-index execution or persisted row-ID routing metadata.
Validation
cargo fmt --allcargo test -p lance io::exec::filtered_read::tests -- --test-threads=1(75 passed)cargo clippy --all --tests --benches -- -D warningsRUSTFLAGS='-D warnings' cargo +nightly-2026-07-13 check -p lance --tests