fix: read indexed column from index cursor in range-seek fast paths - #669
Merged
Conversation
…664) The BETWEEN/LIKE-prefix/IN/forward-comparison index-seek fast paths (src/codegen/select/range_scan.rs) all re-read the indexed column from the table row after IdxRowid+SeekRowid, even though that same column's value is already sitting in the index cursor's own key the seek just matched against — one redundant Column decode per row, on top of the table lookup still needed for the other selected columns. emit_matched_row now recognizes a plain bare-column select list (bare_column_names) and substitutes an index-cursor Column read (emit_indexed_column_read, position 0, with the same REAL-affinity fixup emit_column_read applies) for the one column that matches the seek's indexed column. Any other select-list shape (*, computed expressions) falls back to the unchanged emit_row_via_sink path. Verified: EXPLAIN opcode sequence for read_indexed_range (SELECT id, n, x, f, s FROM bench_data WHERE x > 50000) now matches oracle's shape exactly (Column reads x off the index cursor, not the table). Full test suite and oracle-parity corpus pass; spot-checked BETWEEN/IN/*/computed-expression queries byte-for-byte against oracle. Benchmark note: cargo bench --bench crud -- read_indexed_range shows no measurable change at the 1mb fixture (within noise, no 50mb variant exists for this scenario) — the eliminated Column read is a small fraction of per-row cost next to the btree seek/page touch and the other four column reads. Landing as a correctness/opcode-parity fix, not a benchmarked performance win. spend: ~1x estimate (small). Refs #664 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
iheitlager
force-pushed
the
fix/664-indexed-range-column-reuse
branch
from
August 30, 2026 11:48
5453816 to
aaaa1f9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/codegen/select/range_scan.rs) all re-read the seeked-on indexed column from the table row afterIdxRowid+SeekRowid, even though that column's value is already sitting in the index cursor's own key.emit_matched_rownow recognizes a plain bare-column select list and reads that one column straight off the index cursor instead — any other select-list shape (*, computed expressions) falls back to the original table-cursor read, unchanged.Changes
Fixed
emit_matched_row(range_scan.rs) substitutes an index-cursorColumnread (position 0, with the sameRealAffinityfixupemit_column_readapplies) for the select-list column matching the fast path's indexed column.emit_matched_row:try_compile_between_seek,try_compile_like_prefix_seek,try_compile_in_list_seek,try_compile_forward_comparison_seek.Testing
cargo test --lib— 979 passedcargo test --test '*'— full integration/oracle-parity suite, no failurescargo clippy --all-targets— cleanEXPLAINopcode sequence forread_indexed_range(SELECT id, n, x, f, s FROM bench_data WHERE x > 50000) now matches oracle's shape exactly — verified by diffing againstsqlite3's ownEXPLAINBETWEEN,IN,SELECT *, a computed expression (x*2), and>=— all fall back or apply correctlycargo bench --bench crud -- read_indexed_range— no measurable change at the 1mb fixture (within noise; no 50mb variant exists for this scenario). The eliminatedColumnread is a small fraction of per-row cost next to the btree seek/page touch and the other four column reads still read from the table.Honest framing: this lands as a correctness/opcode-parity fix (satisfies acceptance criteria #1, #2, #4 from #664) rather than a benchmarked performance win (criterion #3 not met at this scale) — flagging this explicitly rather than overclaiming.
spend: ~1x estimate (small).