fix(index): sort JSON-path values once after extraction, not the raw column#7835
Draft
wjones127 wants to merge 1 commit into
Draft
fix(index): sort JSON-path values once after extraction, not the raw column#7835wjones127 wants to merge 1 commit into
wjones127 wants to merge 1 commit into
Conversation
…column A JSON-path scalar index trains its target (e.g. btree) on the value extracted from the JSON column at `path`, not on the raw JSON column itself. The scanner's upstream sort only orders by the raw column, so for targets that require value-ordered input (btree, whose per-page min/max come from the first/last row), the extracted stream was not actually sorted by value. This silently corrupted page min/max stats, so range and equality queries missed rows -- particularly floats not exactly representable in float64, whose storage order diverges most from their numeric order. `JsonTrainingRequest::criteria()` now overrides the target's `Values` ordering to `None` when delegating to the scanner, since a raw-column sort can't help the extracted value anyway. `train_index` sorts the extracted `(value, row_id)` stream itself, once, right before handing it to the target trainer. Fixes lance-format#7485
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: QUIET Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
Problem
A JSON-path scalar index (
target_index_type=btree) returns wrong results when theindexed path holds float64 values that are not exactly representable (e.g.
40.1,-3.2): ranges come back empty and equality misses rows.Fixes #7485.
Root cause
The btree trainer requires its input sorted by value (page min/max are taken from the
first/last row of each page).
scan_training_datasorts by the raw JSON column whenthe target requests
TrainingOrdering::Values, butJsonIndexPluginextracts adifferent value (the value at
path) from that column downstream, so the extractedstream is not actually sorted by value. Silently corrupted page stats then cause range
and equality lookups to skip pages that hold matching rows.
Relationship to #7493, #7771, #7819
All three open PRs diagnose this correctly and fix it by adding a second
SortExecafter JSON extraction, on top of the raw-column sort the scanner already performs. That
raw-column sort is wasted work — it sorts a key nothing downstream uses.
This PR instead has
JsonTrainingRequest::criteria()override the target'sTrainingOrdering::ValuestoTrainingOrdering::Nonewhen delegating to the scanner(the scanner's sort can't help the extracted value anyway), and sorts the extracted
(value, row_id)stream once, intrain_index, right before handing it to the targettrainer. Same correctness fix, one sort instead of two.
Testing
test_json_float_btree_index_unsorted_input(rust/lance-index/src/scalar/json.rs):builds a real JSON/btree index through the plugin trainer/registry with the issue's
repro values fed in raw storage order, and asserts range/equality results across 5
cases. Also asserts
JsonTrainingRequest::criteria().ordering == TrainingOrdering::None.test_json_index_non_exact_floats(python/python/tests/test_scalar_index.py): theissue's repro end to end via
create_scalar_index+json_get_floatfilters.cargo fmt --all,cargo clippy -p lance-index --tests -- -D warnings, anduv run make lintare clean.