Skip to content

feat(gc): optimize chunk tables and delete superseded versions - #50

Merged
JRedeker merged 2 commits into
mainfrom
fix/lgrep-36-version-maintenance
Oct 24, 2026
Merged

JRedeker merged 2 commits into
mainfrom
fix/lgrep-36-version-maintenance

Conversation

@JRedeker

@JRedeker JRedeker commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Every LanceDB write leaves a table version, and nothing removes them. The semantic cache on the maintainer host reached 97 GiB. One 170k-row cache held 16,772 versions: 8.0 GiB of manifests beside 2.0 GiB of data. Opening a 47k-version table took 6.6 s.

Change

  • lgrep gc gains a fourth pass, optimize_caches. It runs LanceDB optimize on each chunks table: compaction, deletion of every version but the latest written more than an hour ago, and index updates. The dry run (default) reports each cache's version count and size.
  • optimize adds new rows to the vector index's existing partitions, as one more segment per run; the index is trained once on the first rows indexed (340 of 169,733 on the cache above). The pass retrains the vector index first whenever the table has one.
  • Vector and hybrid search re-rank candidates by exact distance (refine_factor(10)).
  • Connections recheck the latest table version every 5 s (read_consistency_interval). Without it, a long-lived server handle keeps a version the pass deleted and fails every later search and write until restart.

Evidence (copy of the 170k-row cache)

Before After optimize
Size 9.3 GiB 1.7 GiB
Versions 16,772 3
Rows 169,733 169,733
Top-10 agreement with exact search ~1.0 (index covers 0.2% of rows; search scans) 0.60 retrained, no re-rank; 0.98 with refine_factor(10)
Query time ~270 ms ~22 ms

The run took 275 s and peaked at 2.3 GiB. In a two-process test, a writer that committed during optimize always won and optimize raised a retryable conflict, so the pass reports that cache and the next run retries.

Tests

tests/test_table_maintenance.py: version deletion keeps rows; dry run changes nothing; retrain keeps the index one segment deep across runs (fails without it); an open store reads and writes after another process optimizes (fails without the consistency interval); exact match ranks first through the PQ index, vector and hybrid (21 of 40 without re-ranking); optimize_caches reporting, reclaim, and per-cache failure. Full suite: 1249 passed, 1 xfailed. Reviewed by an independent reviewer; its test and doc fixes are included.

Every LanceDB write leaves a table version behind and nothing removed
them: one 170k-row cache held 16,772 versions, 8.0 GiB of manifests
beside 2.0 GiB of data. `lgrep gc` gains an optimize_caches pass that
runs LanceDB optimize on each chunks table (compaction, deletion of
versions superseded more than an hour ago, index updates).

optimize also adds new rows to the vector index. The index is trained
once on the first rows indexed (340 of 169,733 on that cache), so the
pass retrains it when most rows lie outside it, and vector and hybrid
search now re-rank candidates by exact distance (refine_factor 10).
On that cache top-10 agreement with exact search went from 0.60 to
0.98, at about 22 ms per query against 270 ms for today's scan.

Connections now recheck the latest table version every 5 s. Without
it a long-lived server handle keeps a version the pass deleted and
fails every later search and write until restart.

Refs LGREP-36.
The coverage rule fired only on a cache's first run: optimize then
folds new rows into the stale partitions and adds one index segment
per run. Retraining whenever an index exists keeps it trained on the
current rows and one segment deep. Tests now prove the retrain and the
hybrid re-rank, and the docs state LanceDB's age rule (time a version
was written) correctly.
@JRedeker
JRedeker enabled auto-merge (squash) October 24, 2026 18:44
@JRedeker
JRedeker merged commit f3aa08a into main Oct 24, 2026
4 checks passed
@JRedeker
JRedeker deleted the fix/lgrep-36-version-maintenance branch October 24, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant