Skip to content

feat(index): support distributed LabelList scalar index builds#7223

Merged
jackye1995 merged 2 commits into
lance-format:mainfrom
jackye1995:jack/label-list-distributed-build
Jun 29, 2026
Merged

feat(index): support distributed LabelList scalar index builds#7223
jackye1995 merged 2 commits into
lance-format:mainfrom
jackye1995:jack/label-list-distributed-build

Conversation

@jackye1995

Copy link
Copy Markdown
Contributor

Summary

LabelListIndexPlugin::train_index unconditionally rejected fragment-scoped
training (fragment_ids.is_some()), so a LabelList index could not be built
through the distributed / segmented path (per-fragment execute_uncommitted +
merge_existing_index_segments) the way BTree, Inverted, Bitmap, and FM already
are. This makes LabelList a first-class distributed scalar index.

Changes

  • lance-index/src/scalar/label_list.rs: train_index ignores fragment_ids and
    builds over the already fragment-scoped stream (mirrors FMIndexPlugin); a partial
    index over a fragment subset is correct since it covers exactly those rows. Add
    merge_label_list_indices, which unions the per-segment bitmap states and the
    list_nulls row sets. LabelList wraps a BitmapIndex plus a null-row set and
    distributed segments cover disjoint rows, so this is a cheap union (the same
    operation LabelListIndex::update performs) — no source re-scan. Mirrors
    merge_bitmap_indices but also carries list_nulls.
  • lance/src/index/scalar/label_list.rs (new): merge_segments opens each source
    segment as a LabelListIndex and calls merge_label_list_indices (mirrors
    scalar/bitmap.rs).
  • lance/src/index.rs: merge_existing_index_segments routes all_label_list
    segments (details LabelListIndexDetails) to the new merge; add
    segment_has_label_list_details.
  • lance/src/index/scalar.rs: declare the label_list module.

Covered by test_label_list_merge_existing_index_segments: one LabelList segment per
fragment, merged via merge_existing_index_segments, answers array_has_any across
both fragments with the same row count as a pre-index full scan.

@github-actions github-actions Bot added A-index Vector index, linalg, tokenizer enhancement New feature or request labels Jun 11, 2026
@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.57692% with 60 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rust/lance/src/index/scalar/label_list.rs 65.68% 24 Missing and 11 partials ⚠️
rust/lance-index/src/scalar/label_list.rs 64.06% 11 Missing and 12 partials ⚠️
rust/lance/src/index/create.rs 99.18% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@jackye1995
jackye1995 requested a review from Xuanwo June 16, 2026 22:06
))
})?;
let scalar_index =
super::open_scalar_index(dataset, &field_path, segment, &NoOpMetricsCollector).await?;

@Xuanwo Xuanwo Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can silently convert legacy nullable LabelList segments into a current-format index.

Please reject merging nullable LabelList segments that are missing the list-null metadata, or rebuild from source data instead of writing them as current-format output.

let mut source_indices = Vec::with_capacity(segments.len());
let mut fragment_bitmap = RoaringBitmap::new();
for segment in &segments {
fragment_bitmap |= segment.fragment_bitmap.as_ref().cloned().ok_or_else(|| {

@Xuanwo Xuanwo Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can publish stale coverage and row addresses when any source segment covers retired fragments.

Please compute effective live coverage and filter the merged bitmap state plus list_nulls, or rebuild from live fragments when deleted coverage is present.

LabelListIndexPlugin::train_index rejected fragment-scoped training, so a
LabelList index could not be built through the distributed / segmented path
(per-fragment execute_uncommitted + merge_existing_index_segments) the way
BTree, Inverted, Bitmap, and FM already are. Build over the already
fragment-scoped data stream (mirroring FMIndexPlugin) and add
merge_label_list_indices, which unions the per-segment bitmap states and
list_nulls row sets. Route LabelList segments through merge_existing_index_segments.
@jackye1995
jackye1995 force-pushed the jack/label-list-distributed-build branch from 33be32e to 8570d98 Compare June 26, 2026 21:52
@jackye1995
jackye1995 requested a review from Xuanwo June 27, 2026 07:09
@jackye1995
jackye1995 merged commit f59b484 into lance-format:main Jun 29, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-index Vector index, linalg, tokenizer enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants