fix(scan): reduce large-table global-index planning memory - #678
fix(scan): reduce large-table global-index planning memory#678XiaoHongbo-Hope wants to merge 18 commits into
Conversation
|
Addressed the two review concerns in 483555a:
Validation: table-scan tests 82 passed; streaming Top-K integration passed; cargo clippy for paimon and paimon-datafusion passed with -D warnings. |
483555a to
e11d770
Compare
|
See comments in #672 |
|
Please re-create this optimization without #672 |
JingsongLi
left a comment
There was a problem hiding this comment.
This PR introduces a large, DataFusion-specific execution path instead of addressing the underlying RowID representation problem. The main risks are:
-
Incorrect results with mixed BTree and Bitmap coverage
In FAST mode, the streaming path reads only BTree indexes. If Bitmap indexes cover additional RowID ranges for the same field, matching rows from those ranges can be silently omitted. -
Valid large indexes can fail queries
The streaming reader enforces a hard-coded 256 MiB block limit. A valid hotspot key may legitimately contain more RowIDs than this because all RowIDs for one key are stored in a single BTree value. The query then fails instead of falling back to a normal data scan. -
Existing fallback controls are bypassed
Wide LIKE predicates without a literal prefix may scan every BTree shard while ignoring btree-index.fallback-scan-max-size. This can cause extremely long-running queries and excessive index I/O. -
Repeated planning overhead
Every 250K-RowID batch repeats manifest decoding, pruning, split planning, and file setup. The cache avoids some object-store reads but does not eliminate most of the repeated CPU and planning work. -
Reduced parallelism
The new path processes BTree shards serially and forces the DataFusion scan into a single execution partition. global-index.thread-number is effectively ignored for this path. -
Incomplete and inconsistent coverage
The optimization only applies to DataFusion, BTree indexes, and single-leaf Eq, StartsWith, and Like predicates. Bitmap indexes, compound predicates, range predicates, and other readers/connectors retain the original query-wide materialization problem. -
High maintenance and regression risk
The PR adds a second scan-planning and execution pipeline, including snapshot preparation, manifest caching, ownership assignment, batching, and fallback logic. This duplicates existing behavior and makes correctness across search modes, index types, and connectors harder to maintain.
First, we need to investigate the differences between Rust and Java to understand why Rust's memory usage is exceeding expectations.
If Java also fails to handle the load, we should consider falling back to a full table scan instead of using a global index. Global indexes are designed for small datasets or range queries; attempting to force them to serve other use cases—as discussed in the feedback above—carries significant risk.
|
Summary
StartsWithindex predicateThis version removes the rejected DataFusion-specific streaming path and does not include #672's planner-time LIMIT pushdown, candidate early stop, or hard query-memory fallback.
Why
The Shanghai table currently has roughly 23.6 million manifest entries. Rust previously accumulated all live
DataFileMetavalues before applying global-index row ranges, which amplified scan-planning memory. Java performs a two-pass manifest scan and avoids eagerly loading the BTree null bitmap.Validation
Shanghai DLF/OSS table, under an 8 GiB memory limit:
StartsWithplanning: 13.7 s, 546 MiB peak RSSLocal tests:
cargo fmt --all -- --checkandgit diff --check: passedSQL semantics
In SQL LIKE, an unescaped
_matches any single character. Therefore the original pattern with several underscores is a broad residual LIKE and cannot safely become a prefix index lookup. Literal underscores must be escaped, for example:That escaped form is recognized as an exact prefix and completed within the memory limit above.