[core] Add primary-key vector read kernel#517
Open
JunRuiLee wants to merge 3 commits into
Open
Conversation
048df10 to
ff5bb39
Compare
ff5bb39 to
f336b6a
Compare
f336b6a to
ff5bb39
Compare
Rust equivalent of Java `PrimaryKeyVectorPositionReader` (reader-kernel subset of apache/paimon#8576). Given one data file, a set of selected 0-based physical positions, and an optional position->score map, it materializes the selected rows and appends internal metadata columns `_PKEY_VECTOR_POSITION` (+ optional `_PKEY_VECTOR_SCORE`). Physical positions are recovered from the `_ROW_ID` column the existing selective read emits (position = _ROW_ID - first_row_id), injected internally and stripped from the output, so a deletion vector dropping rows never desyncs position/score alignment. Reuses the existing single-file read (`read_single_file_stream`, its `_ROW_ID` mechanism, DV intersection) rather than a new read path. Validation (all DataInvalid): empty / negative / out-of-range positions; scores key-set must equal the selected positions; a requested `_ROW_ID` or a reserved metadata column name is rejected; a row-filtering predicate is rejected (`_ROW_ID` + a residual filter desync); a data file without first_row_id. Adds three `pub(super)` `DataFileReader` accessors (read_type, has_row_filtering_predicate, with_read_type) for the sibling module. No crate-level caller yet, so the module and accessors carry a temporary `#[allow(dead_code)]`.
Rust equivalent of Java `PrimaryKeyIndexedSplitRead` (read-path subset of apache/paimon#8576). `PkVectorIndexedSplit` carries one data file + inclusive physical-position ranges + an optional aligned score array; `PkVectorIndexedSplitRead` validates the split, expands the ranges into an ascending position set and a position->score map, and delegates to the sibling position reader. A pure consumer: no bucket/ANN search, no orchestration, no serialization. Validation: exactly one data file; ranges within [0, row_count), strictly ascending and non-overlapping (touching allowed); score length must match the expanded positions. No crate-level caller yet, so it carries a temporary `#[allow(dead_code)]`.
Rust equivalent of Java `PrimaryKeyVectorRead` + the read subset of `PrimaryKeyVectorResult.splits()` (apache/paimon#8579). Per-bucket search via `bucket_search`, cross-bucket global Top-K merge, grouping survivors by data file into `PkVectorIndexedSplit`s, and lazy materialization via `PkVectorIndexedSplitRead`. Global Top-K is a full sort + truncate over the collected candidates (N <= buckets * limit) on a five-level BEST_FIRST key (distance, partition bytes, bucket, file name, row position; `total_cmp` for NaN-safety). Grouping fails loud on cross-split ambiguity, duplicate (file, position), or a hit referencing a file absent from its bucket split. Adds `VectorSearchMetric::distance_to_score` (mirrors Java `PrimaryKeyVectorResult.score(distance)`). Inputs are synthetic per-bucket splits; snapshot/manifest planning, table routing, and real dependency construction are not yet implemented, so the module carries a temporary `#[allow(dead_code)]`.
ff5bb39 to
ae7342f
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.
Purpose
Linked issue: part of #514 — this PR implements the crate-private PK-vector read kernel / orchestration layer. It does not close the issue.
This is the Rust read-kernel counterpart of Apache Paimon Java apache/paimon#8576 (
PrimaryKeyVectorPositionReader/PrimaryKeyIndexedSplitRead) plus the read-kernel subset of apache/paimon#8579 (PrimaryKeyVectorRead+PrimaryKeyVectorResult.splits()). It is intentionally not the full user-facing PK-vector search integration.Given synthetic per-bucket search inputs, this PR can:
#516has already absorbed the current Java-master behavior for inactive ANN sources (file == null -> continue) and bounded heap merging, so this PR builds on that behavior. The inactive-source handling is therefore intentional and aligned with current Java master, not a fail-loud mismatch.Scope
In scope:
pk_vector_position_read.rs— Rust equivalent of JavaPrimaryKeyVectorPositionReader.pk_vector_indexed_split_read.rs— Rust equivalent of JavaPrimaryKeyIndexedSplitRead.pk_vector_orchestrator.rs— synthetic-input orchestration mirroring the read-kernel part of JavaPrimaryKeyVectorRead/PrimaryKeyVectorResult.splits().VectorSearchMetric::distance_to_score, used when converting final distances into Java-compatible higher-is-better scores.Out of scope for this PR, handled by the follow-up integration PR:
PrimaryKeyVectorScan/ snapshot and index-manifest planning;VectorSearchBuilder/ table routing and public API wiring;GlobalIndexSearchMode::Fastrouting behavior;Because there is no crate-level production caller for these new reader/orchestrator modules yet, they intentionally keep narrow
#[allow(dead_code)]annotations. The follow-up integration PR wires the production caller and removes the allowances for the wired search path.Brief Change Log
pk_vector_position_read.rsRust equivalent of Java
PrimaryKeyVectorPositionReader._PKEY_VECTOR_POSITION(Int64, always);_PKEY_VECTOR_SCORE(Float32, only when scores are supplied)._ROW_IDchannel (position = _ROW_ID - first_row_id) instead of guessing from batch offsets._ROW_IDinternally and strips it from final output.read_single_file_stream._ROW_ID, missingfirst_row_id, predicate-bearing readers, empty positions, out-of-range positions, and score-key mismatches.pk_vector_indexed_split_read.rsRust equivalent of Java
PrimaryKeyIndexedSplitRead.PkVectorIndexedSplit: one data file + inclusive physical-position ranges + optional scores aligned to expanded position order.PkVectorPositionRead.pk_vector_orchestrator.rsRust equivalent of the synthetic-input read-kernel part of Java
PrimaryKeyVectorReadandPrimaryKeyVectorResult.splits().bucket_searchfor each synthetic bucket split.VectorSearchMetric::distance_to_score.PkVectorIndexedSplits for materialization.(file, position), or a hit referencing a file absent from its bucket split.Validation
Synthetic unit/e2e tests cover:
_ROW_IDvalues;Validated locally:
cargo fmt --all --checkcargo clippy -p paimon --lib --tests -- -D warningscargo test -p paimon pk_vector --libFull public-path validation with snapshot/index-manifest planning and real ANN/exact dependencies is intentionally deferred to the follow-up integration PR.
API and Format
No storage-format change. All additions are crate-private (
pub(crate)/pub(super)); no public API is added or changed in this PR.Documentation
No user-facing documentation changes.