Skip to main content
Applies to: Embedded ❌, Enterprise ✅ LanceDB Enterprise separates query planning from index execution and data reads so that search can use the memory, CPU, and caches of multiple machines. A query node plans and coordinates a query. Executors search indexes, read table data, and return partial results for the query node to combine. For the service components and overall request paths, see Architecture.

Search architecture

LanceDB Enterprise prioritizes horizontal scalability. Index execution on a single node can be limited by the memory available to cache the index for fast search and by the CPU available to execute queries. Dividing one logical index into multiple index segments lets each segment be distributed to an executor, cached independently, and searched in parallel with other segments. The two serving components have different responsibilities: Eligible scalar index operations can also execute on executors. See scalar indexes and filtering for index types and query syntax. For example, consider a vector index with six segments served by three executors. Each executor searches its two segments and returns its best 10 candidates. The query node compares the candidates returned by all three executors and selects the final 10. This example assumes enough matching rows and the default search path without additional reranking.

Tiered index cache

Executors cache index structures in memory, and extend that cache onto local disk when the disk tier is enabled. See Tiered Index Cache for how the two tiers work together and how the disk tier’s budget is shared and sized; ask your deployment operator about enabling it on your cluster.

Create and query an IVF-RQ index

Use the regular table API. These examples assume table is an open Enterprise table with a vector column and the query vector is compatible with that column. For connection setup, see connect to LanceDB.
Enterprise builds indexes in the background. Submitting index creation does not mean the index is ready; check index status before evaluating indexed search. These examples explicitly select 5 bits per dimension. See the shared docs for RaBitQ and num_bits, index creation parameters, and vector search. For the fast, normal, and accurate latency/recall modes, see tuning approx_mode. The Rust SDK currently exposes that query setting; the examples above use the default mode. FTS work is organized by inverted index. Compatible operations targeting the same table and text column can execute together on executors over that index’s segments. Operations targeting different indexed columns can execute separately, with their results combined on the query node according to the query. For example, suppose an articles table has separate FTS indexes on title and body. A query asks for rows whose title matches the exact term vector or whose body contains the phrase nearest neighbor:
  1. The query node plans the title and body index searches separately.
  2. Executors search the relevant segments of each index.
  3. The query node combines the scored rows according to the cross-column query’s semantics and returns the requested results.

Local and global scoring

Distributed FTS defaults to local scoring. Each executor uses statistics from its assigned segments to calculate BM25 scores. This avoids a separate statistics round, but document frequencies and average document lengths can differ between executors. Merging their scores can therefore produce a different ranking from scoring with statistics across the entire index. Global scoring adds a statistics round before search. The query node collects and aggregates document counts, token counts, and query-term document frequencies across the target FTS index. Executors then score with the shared statistics before the query node combines their results. The statistics are global to that index, not blended across all text columns in the table. Both modes combine results. The difference is the statistics used during scoring on executors; global mode does not rescore the returned rows on the query node. It trades an additional statistics round for consistent BM25 statistics across executors. When term frequencies and document lengths are similarly distributed across index segments, local scoring can produce rankings comparable to global scoring. If segments contain substantially different document populations, prefer global scoring for consistent statistics across the index, at the cost of an additional statistics round and higher query latency. Global scoring is a query node setting, configured at the deployment level. See full-text search for query syntax and FTS indexes for index configuration. A table can be larger than any single node’s local storage. Enterprise keeps the durable table in object storage and distributes data reads and caches across executors. An executor needs capacity for its cached working set rather than a complete local copy of the table. With fragment-based data routing, reads for a data fragment go to a serving executor. Different fragments can be served and cached on different executors. The following example shows six fragments served by three executors:

NVMe data caching

The data page cache stores pages read from table fragments on local disk, including NVMe SSDs. On a cache hit, the executor reads the page from local disk; on a miss, it fetches the page from object storage and fills the cache for subsequent reads. The cache holds accessed pages, not necessarily every byte of each fragment assigned to an executor. See Data Page Cache for how it’s structured and sized.

Inspect execution

Use analyze_plan() (analyzePlan() in TypeScript) to understand how a query executes and troubleshoot slow searches. It runs the query and returns the execution plan with runtime metrics. Using the same table and query vector as above:
Inspect the plan to check which indexes are used, which operations run on query nodes or executors, and where execution time is spent. Compare index search with data retrieval to identify expensive work. Repeating the query can also help distinguish cold-cache reads from warm-cache performance.