[core] Optimize bitmap range conversion and selected-row reads - #10007
Merged
JingsongLi merged 1 commit intoSep 20, 2026
Merged
Conversation
leaves12138
approved these changes
Sep 20, 2026
leaves12138
left a comment
Contributor
There was a problem hiding this comment.
LGTM. Reviewed the selected-row iterator seeking/caching and the bitmap-to-ranges path-selection heuristic. The change avoids repeated selection-prefix traversal while preserving file-relative positions, skip/release behavior, and shared selection ownership. Range construction remains exact, with no storage or split-format changes.
Validation against b5bcf9b:
- 295 focused tests passed across Common, Parquet, Core, and Lance, including BTree V1/V2, column-group reads, indexed splits, and deletion vectors.
- Independent randomized checks passed for 10,296 selection batches and 757 bitmap/range comparisons, including unsigned 32-bit and 64-bit boundaries.
- Non-fast-build compilation/checks passed for paimon-common and its reactor prerequisites.
No blocking correctness or compatibility issues found. CI is still running; this approval does not imply that the remaining checks have completed.
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
Reduce traversal overhead when scalar indexes return many row IDs, particularly for Data Evolution tables with column-group reads. This PR changes two shared traversal helpers and their regression tests only; it does not add a memory-budget option, scan fallback, cost model, or storage/split-format change.
1. Seek within the selection instead of rescanning its prefix for every batch
FileRecordIterator.selectionpreviously created a fresh iterator over the whole file selection for each batch. A batch starting late in the file walked all earlier selected positions again. With many batches and a large selection, this repeated-prefix work dominates the actual read.Use
RoaringBitmap32.nextValueto seek directly to the current file-relative position and cache the next selected position. Bothnext()andskip()use the same check; unselected gaps do not trigger a fresh seek for every row. Batch release, selection ownership, and unsigned 32-bit position boundaries are covered by tests.2. Avoid the select-based bitmap-to-ranges path for dense but short runs
RoaringNavigableMap64previously sampled adjacent values at the middle and tail. A pattern such as nine matching rows followed by one gap can look dense to those samples, yet create many short ranges. Repeated rank-basedselectcalls are expensive for that shape.Probe longer contiguous windows before selecting that path. Split each window into two halves so that an isolated gap inside a long run does not force a full value-by-value traversal. The existing exact range construction is unchanged: gaps are never filled or approximated.
Performance
Local synthetic benchmark: JDK 8, RoaringBitmap 1.2.1, default Parquet configuration, Data Evolution column groups (
key/flagand a separate payload group). BTree V1 and V2 were tested separately; V2 was explicitly enabled. The payload was checked against the key while fully consuming the results.Each variant was warmed up once, followed by three rotated rounds; the table reports median planning + full-read latency for 1.2 million rows, excluding table creation, writes, and index construction.
How the measurements relate to the changes:
Measurement scope and limitations:
2f16b3872b, comparing the old and retained new traversal implementations. At that time an experimental range-memory guard was present but disabled on both sides, so these numbers do not include fallback-to-scan gains. That guard and its configuration are absent from this PR. These are not newly measured timings of the final rebased commit.Tests
Regression coverage avoids wall-clock thresholds:
next/skip, non-materializingskip, release forwarding, an unchanged shared selection, and unsigned 32-bit boundaries.After rebasing onto master
54d8596ce7, the focused regression suite passed 290 tests: Common 29, Parquet 14, Core 227, and Lance 20. Coverage includes BTree V1/V2, bitmap/multivalue indexes, vector/full-text filtering, indexed splits, column-group reads, and deletion vectors.mvn -pl paimon-lance -am -Pfast-build \ -DfailIfNoTests=false -DwildcardSuites=none \ -Dtest=FileRecordIteratorTest,RoaringNavigableMap64Test,RowRangeIndexTest,BtreeGlobalIndexTableTest,BitmapGlobalIndexTableTest,MultiValueGlobalIndexTableTest,VectorSearchBuilderTest,FullTextSearchBuilderTest,IndexedSplitTest,IndexedSplitRecordReaderTest,DataEvolutionReadTest,DataEvolutionSplitReadTest,PrimaryKeyIndexedSplitReadTest,DataEvolutionFileIndexTest,DataEvolutionDeletionVectorTest,ParquetFormatReadWriteTest,LanceBTreeGlobalIndexTest \ testOn the local JDK 8 environment, Mockito's dynamic attach was unavailable, so the test command additionally preloaded the project's Byte Buddy 1.10.13 agent via
-DextraJavaTestArgs=-javaagent:<local-agent-jar>. No dependency or build-file changes were needed.Non-fast-build verification also passed: