vector-store: interval-based Tantivy commits#521
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces deferred/periodic commit behavior for the Tantivy-backed full-text index to avoid committing on every document update, and adds an end-to-end validator test that exercises BM25 over a large document set.
Changes:
- Add pending-commit tracking to the Tantivy FTS actor, committing on an interval and/or after enough pending bytes accumulate.
- Update Tantivy unit tests to poll for visibility (since commits are deferred) and make the commit interval configurable in tests.
- Optimize validator FTS document insertion by preparing the CQL statement once, and add a
fts_large_document_sete2e test (10k docs) with basic timing instrumentation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/vector-store/src/fts_index/tantivy.rs | Adds deferred commit machinery (pending bytes/dirty flag + interval tick) and updates unit tests accordingly. |
| crates/validator/src/fts.rs | Reuses a prepared insert statement, adds duration logging helper, and introduces a large dataset FTS e2e test. |
Comments suppressed due to low confidence (1)
crates/vector-store/src/fts_index/tantivy.rs:693
- This test can become a false positive with the new deferred-commit behavior: counting immediately after
add_doccan return 0 simply because the index hasn't committed yet. Waiting at least one commit interval before asserting makes it validate that the document truly was not indexed when memory allocation is denied.
add_doc(&sender, 1, "should not be indexed").await;
let key = make_index_key();
let count = sender.count(key).await.unwrap();
assert_eq!(count, 0);
1baad0a to
c9038d6
Compare
c9038d6 to
d06911d
Compare
d06911d to
4cf0366
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
crates/vector-store/src/fts_index/tantivy.rs:426
tokio::select!cannot have an arm starting with an enum variant pattern (FtsIndex::Stats { .. } => { .. }). This will not compile, and it also suggestsFtsIndex::Statsis not handled in thematch msgblock, making that match non-exhaustive.
FtsIndex::Stats { index_key, tx } => {
let Some(state) = get_state(&states, table.as_ref(), &index_key) else {
_ = tx.send(Ok(FtsStats::default()));
continue;
};
2bf1a5b to
05a79de
Compare
05a79de to
72dd540
Compare
093156c to
c78703a
Compare
48e2e43 to
25a8a98
Compare
|
AI says that the merge queue failure was caused by the infra, base on this output (ANNOTATIONS section) But I am still looking at this. |
I was able to reproduce locally. |
Before, the fixture created the index and documents were added to the created index. In this scenario, the index had to search and poll until expected results. Now the index is created after documents are added and before proceeding with the test, we wait until the index is built. This also more properly validates the index readinessimplementation. The crud tests verify that the index also properly handles post-built updates.
Test case that adds 10k documents to the FTS index and runs a search query to validate that the index is working correctly. Measure (but do not assert) the time it takes to index the documents and run the search query. Fixes VECTOR-636
a152c48 to
a8304de
Compare
|
I fixed the flaky test. The problem was a race condition: the timer was being reset before spawning the task that actually adds the document to the writer. As a result, the timer handler could run before the spawned task, committing no documents. I changed the approach and dropped the timer reset altogether. Instead, I now commit immediately after the add/remove handlers inside the same spawned task. This change was introduced in a dedicated commit: 515f882. @ewienik could you please share you opinion? |
a8304de to
515f882
Compare
Changes seems ok. Could you combine them with the correct previous commit to stick with single implementation in the PR? |
Previously, every AddDocument/RemoveDocument operation triggered an immediate tantivy commit and reader reload, which was very slow; the indexing of 10k small documents was taking 2 minutes. Replace the per-operation commit with a periodic tick (every 3s by default) driven by a tokio::select! loop. Additionally index tracks number of uncommitted documents and triggers the commit when documents exceeds 10k threshold. This prevents from unlimited growth of uncommitted documents. VECTOR-621
By default Tantivy reader is configured to auto reload after commit after some delay. Disable Tantivy auto reload as we call it manually. We need to call this manually so that we correctly notify by dropping the InProgress guard that documents have been processed and can be searchable.
515f882 to
0ae51c9
Compare
Done. |
This PR improves FTS indexing performance by replacing per-document Tantivy commits with an interval-based commit strategy. Commits are now triggered by a time interval (3 seconds). This reduces indexing time for 10,000 small documents from roughly 2 minutes to under 1 second.
Additionally, to prevent unlimited uncommitted documents, we force a commit when the number of pending documents exceeds the 10k threshold.
This change also fixes double reader reload. In default tantivy reader configuration (that we have) reload happens automatically after commit. My must take control over reload to drop InProgress correctly after reload.
A new validator test covers correctness at scale: it inserts 10,000 documents, waits for the index to catch up, then asserts that a rare-term BM25 search returns only the expected needle documents and that a common-term search respects the query LIMIT.
Indexing and query durations are measured and logged.
Fixes: VECTOR-636
Reference: VECTOR-621