Files
lancedb/docs/web/indexing/vector-index.mdx
T
Jack Ye 19f8f396ec docs: consolidate pages that were split for no reason
Ten merges and renames, all in one direction: fewer pages, each covering a whole
subject.

Table absorbs schema evolution and versioning. Vector search absorbs
multi-vector. Explain absorbs explain analyze. Reranking was seven pages -- an
overview and six rerankers of a few dozen lines each -- and is now one. The
vector index page absorbs quantization, which was only ever a parameter of it.

Indexing moves to Manage, where the other catalog objects are. The operational
half stays in Operate as one Indexing page, absorbing GPU indexing -- which was
filed in sophon despite importing lancedb's snippets and being mostly
open-source content with one Enterprise-badged section.

Performance was a single page aggregating tips for four unrelated operations,
which is hard to keep current. Each section now sits with the operation it is
about: ingestion tips on Insert, index tips on Indexing, compaction tips on
Compaction, query tips on Search.

Data Types leaves Concepts. The type reference belongs in the SQL reference,
which already described the same types from the query side; Table now carries a
short summary that points there. The multimodal material it had absorbed is its
own page again, since storing blobs is a task rather than a type definition.

Query becomes Semantic Search, Branches becomes Branch, and the Enterprise
Security page becomes Compliance.

Redirects cover every moved URL, and 30 files were repointed at the merged
anchors.
2026-09-14 00:57:26 -07:00

453 lines
25 KiB
Plaintext

---
title: "Vector Indexes"
sidebarTitle: "Vector Index"
description: "Build and optimize LanceDB vector indexes, including IVF, HNSW and binary quantized indexes."
icon: "arrow-up-right-dots"
---
import {
PyVectorIndexConfigureIvf as VectorIndexConfigureIvf,
PyVectorIndexSetup as VectorIndexSetup,
PyVectorIndexBuildIvf as VectorIndexBuildIvf,
PyVectorIndexNestedField as VectorIndexNestedField,
PyVectorIndexAsyncConfig as VectorIndexAsyncConfig,
PyVectorIndexQueryIvf as VectorIndexQueryIvf,
PyVectorIndexBuildHnsw as VectorIndexBuildHnsw,
PyVectorIndexQueryHnsw as VectorIndexQueryHnsw,
PyVectorIndexBinarySchema as VectorIndexBinarySchema,
PyVectorIndexBinaryAddData as VectorIndexBinaryAddData,
PyVectorIndexBinaryBuildIndex as VectorIndexBinaryBuildIndex,
PyVectorIndexBinarySearch as VectorIndexBinarySearch,
PyVectorIndexCheckStatus as VectorIndexCheckStatus,
PyVectorIndexNprobes as VectorIndexNprobes,
PyVectorIndexDistanceRange as VectorIndexDistanceRange,
PyVectorIndexBypassRecall as VectorIndexBypassRecall,
PyVectorIndexCustomName as VectorIndexCustomName,
} from '/snippets/indexing.mdx';
You can create and manage multiple vector indexes on any Lance dataset. LanceDB offers two kinds of vector indexing algorithms: **Inverted File (IVF)** and **Hierarchical Navigable Small World (HNSW)**.
<Info>
**IVF + HNSW**
In LanceDB, HNSW is not exposed as a top-level vector index. Instead, it's available as a sub-index inside IVF partitions. What this means in practice is that vectors are first partitioned by IVF, then each selected partition is searched using an HNSW graph. LanceDB supports the unquantized variant `IVF_HNSW_FLAT`, along with quantized variants such as `IVF_HNSW_PQ` and `IVF_HNSW_SQ`. This combines IVF's scalability with HNSW's higher-recall ANN search within partitions.
</Info>
### Manual Indexing {#manual-indexing}
If using LanceDB OSS, you will have to create the vector index manually, by calling `table.create_index()`, and updating the index as new data arrives and tuning its parameters is also a manual process.
### Automatic Indexing {#automatic-indexing}
<Badge color="red">Enterprise-only</Badge>
Vector indexing is managed **automatically** in LanceDB Enterprise. As soon as data is updated, the system updates the index and optimizates it. *This is done asynchronously as a background process*.
When you create a table in LanceDB Enterprise, LanceDB automatically:
- Infers the vector columns from the schema
- Create an optimized `IVF_PQ` index without manual configuration
- Automatically configure indexing parameters
The default distance is `l2` (Euclidean).
<Note>
You can call `create_index()` with different parameters to create a new index -- this replaces any existing index.
Although the `create_index` API returns immediately, the building of the vector index is asynchronous. To wait until all data is fully indexed, you can specify the `wait_timeout` parameter.
</Note>
Use the same distance metric for index creation and search. Once a vector index exists, queries use the metric stored with that index. If you need to confirm an async build or refresh is finished, `wait_for_index(...)` waits for the named index to exist and for `index_stats(...)` to report `num_unindexed_rows == 0`; it can time out if new writes keep arriving.
Rows appended after an index build remain outside that index until optimization refreshes it. Normal
search still checks those unindexed rows with a slower fallback path; `fast_search()` skips that
fallback and searches only indexed rows.
## Choose the Right Index {#choose-the-right-index}
Use this table as a quick starting point for choosing the right index type and quantization method for your use case:
| If your top priority is... | Use this index | Why | Typical compressed size vs. raw vectors |
| :--- | :--- | :--- | :--- |
| Highest recall / no quantization | `IVF_HNSW_FLAT` | Uses raw vectors inside the IVF+HNSW structure, avoiding quantization loss. | Around raw vector size plus HNSW graph overhead |
| Best recall/latency trade-off | `IVF_HNSW_SQ` | Combines IVF partitioning with HNSW graph search for strong quality at low latency. | Typically a little larger than `1/4` of raw size |
| Maximum compression | `IVF_RQ` | RaBitQ-style quantization with very strong compression. | Around `1/32` of raw size |
| Higher accuracy at small dimensions (`dimension <= 256`) | `IVF_PQ` | On small-dimensional vectors, `IVF_PQ` often provides higher accuracy with similar performance compared to `IVF_RQ`. | Usually `1/64` to `1/16` of raw size (depends on `num_sub_vectors`) |
<Warning>
If your vector search frequently includes metadata filters (`where(...)`), prefer `IVF_RQ` or `IVF_PQ`. In filtered workloads, HNSW-backed IVF indexes such as `IVF_HNSW_FLAT` and `IVF_HNSW_SQ` can show higher latency variance.
</Warning>
Compression ratios are practical rules of thumb and can vary with vector distribution, metric, and configuration.
For small dimensions, choose `IVF_PQ` for accuracy, not for guaranteed higher compression than `IVF_RQ`.
### Index Tuning {#index-tuning}
Start with these values, then tune for your workload:
- HNSW-backed IVF indexes (`IVF_HNSW_FLAT`, `IVF_HNSW_SQ`, `IVF_HNSW_PQ`)
- `num_partitions`: start at `num_rows // 1,048,576` (rounded to an integer)
- Lower `num_partitions` can reduce search latency, but index build may become slower because partitions are larger.
- `ef_construction`: start at `150`; increase for better recall, decrease for faster indexing.
- `IVF_RQ`
- `num_partitions`: start at `num_rows // 4096` (rounded to an integer). This is a strong default for most datasets.
- `IVF_PQ`
- `num_partitions`: start at `num_rows // 4096` (rounded to an integer).
- `num_sub_vectors`: start at `dimension // 8`. Increase for better recall, decrease for faster search and smaller indexes.
- For small dimensions (`dimension <= 256`), `IVF_PQ` is often preferred over `IVF_RQ` for better accuracy at similar query performance.
## Example: Construct an IVF Index {#example-construct-an-ivf-index}
In this example, we will create an index for a table containing 1536-dimensional vectors. The index will use IVF_PQ with L2 distance, which is well-suited for high-dimensional vector search.
Make sure you have enough data in your table (at least a few thousand rows) for effective index training.
### Index Configuration {#index-configuration}
Sometimes you need to configure the index beyond default parameters:
- Index Types:
- `IVF_HNSW_FLAT`: highest recall, with no vector quantization
- `IVF_HNSW_SQ`: best recall/latency trade-off
- `IVF_RQ`: best compression for large, high-dimensional datasets
- `IVF_PQ`: often higher accuracy than `IVF_RQ` for small dimensions (`<= 256`) at similar query performance
- `metrics`: default is `l2`, other available are `cosine` or `dot`
- When using `cosine` similarity, distances range from 0 (identical vectors) to 2 (maximally dissimilar)
- `num_partitions`: use index-specific starting points from the section above:
- HNSW-backed IVF indexes (`IVF_HNSW_FLAT`, `IVF_HNSW_SQ`, `IVF_HNSW_PQ`): `num_rows // 1,048,576`
- `IVF_RQ` and `IVF_PQ`: `num_rows // 4096`
- `target_partition_size`: alternative IVF sizing knob that asks LanceDB to derive the partition
count from a target number of rows per partition. If you set both `num_partitions` and
`target_partition_size`, `num_partitions` takes precedence.
- `num_sub_vectors`: applies to `IVF_PQ`; start with `dimension // 8`. Larger values often improve recall but can slow search.
Let's take a look at a sample request for an IVF index:
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexConfigureIvf}
</CodeBlock>
</CodeGroup>
### 1\. Setup {#1-setup}
Connect to LanceDB and open the table you want to index.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexSetup}
</CodeBlock>
</CodeGroup>
### 2\. Construct an IVF Index {#2-construct-an-ivf-index}
Create an `IVF_PQ` index with `cosine` similarity. Specify `vector_column_name` if you use multiple vector columns or non-default names. For a vector field nested inside a struct, use dot notation (e.g. `image.embedding`); see [Selecting the vector column](/search/vector-search#selecting-the-vector-column) for the full syntax. You can switch `index_type` to `IVF_RQ`, `IVF_HNSW_SQ`, or `IVF_HNSW_FLAT` depending on your recall/latency/compression target.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBuildIvf}
</CodeBlock>
</CodeGroup>
#### Indexing nested vector fields {#indexing-nested-vector-fields}
If your vector column lives inside a struct, pass its full dotted path as `vector_column_name`. The same path is used at query time and is what `list_indices()` reports under `columns`:
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexNestedField}
</CodeBlock>
</CodeGroup>
<Note>
Nested paths follow Lance field-path semantics: dot-separate each struct field from root to leaf (for example, `image.thumbnail.embedding`). The same convention applies to FTS and scalar indexes.
</Note>
### Async API and Config Objects {#async-api-and-config-objects}
With asynchronous Python connections, create vector indexes with `await table.create_index("vector", config=...)`. The `config` object carries the same index choices you configure in the synchronous API, such as distance metric, partition count, and quantization settings:
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexAsyncConfig}
</CodeBlock>
</CodeGroup>
Use these Python config classes for the index types shown on this page:
| Index type | Python config class |
| :--- | :--- |
| `IVF_FLAT` | `IvfFlat` |
| `IVF_PQ` | `IvfPq` |
| `IVF_RQ` | `IvfRq` |
| `IVF_SQ` | `IvfSq` |
| `IVF_HNSW_FLAT` | `IvfHnswFlat` |
| `IVF_HNSW_PQ` | `IvfHnswPq` |
| `IVF_HNSW_SQ` | `IvfHnswSq` |
### 3\. Query the IVF Index {#3-query-the-ivf-index}
Search using a random 1,536-dimensional embedding.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexQueryIvf}
</CodeBlock>
</CodeGroup>
#### Search Configuration {#search-configuration}
Core knobs available on a vector search call:
| Parameter | Description |
| :--- | :--- |
| `limit` | Number of results to return (`k`). |
| `nprobes` | Shorthand that sets both `minimum_nprobes` and `maximum_nprobes` to the same value. LanceDB auto-tunes this by default. |
| `minimum_nprobes` | Partitions that are *always* scanned. Higher values raise recall at the cost of latency. |
| `maximum_nprobes` | Upper bound on partitions scanned. The partitions above `minimum_nprobes` are only searched if the initial pass does not return enough results — useful for narrow filters. Set to `0` to remove the cap. |
| `ef` | HNSW search-time exploration factor. Relevant for `IVF_HNSW_FLAT` and `IVF_HNSW_SQ`; start around `1.5 * k` and increase up to `10 * k` for higher recall. |
| `refine_factor` | Reads additional candidates and reranks them in memory to recover recall lost to quantization. |
<Note>
**Filtered queries and adaptive nprobes.** When a `where(...)` filter is active, LanceDB starts by scanning `minimum_nprobes` partitions and only extends toward `maximum_nprobes` if fewer than `limit` rows survive the filter. Setting `minimum_nprobes == maximum_nprobes` (or calling `nprobes(n)`) disables this adaptive behavior and fixes the partition count.
</Note>
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexNprobes}
</CodeBlock>
</CodeGroup>
Recommended `nprobes` behavior by index type:
| Index type | Guidance |
| :--- | :--- |
| `IVF_HNSW_FLAT`, `IVF_HNSW_SQ` | Keep the auto-tuned `nprobes`, then tune `ef` first. Expect higher latency variance under filtered search. |
| `IVF_RQ` | Keep auto-tuned `nprobes`; raise only when recall is insufficient. |
| `IVF_PQ` | Keep auto-tuned `nprobes`; raise when recall is insufficient. Often preferred over `IVF_RQ` when `dimension <= 256`. |
#### Advanced Search Controls {#advanced-search-controls}
These controls are useful for thresholded retrieval, recall measurement, and working around index-level metric constraints.
| Method | Description |
| :--- | :--- |
| `distance_range(lower_bound, upper_bound)` | Return only rows whose distance falls within `[lower_bound, upper_bound)`. Either bound is optional. Useful for near-duplicate detection or "close-enough" matching. |
| `bypass_vector_index()` | Skip the ANN index and perform an exhaustive (flat) scan. Primary uses: (1) compute ground-truth results to measure ANN recall@k, and (2) query with a metric the index was not built for (e.g., a non-cosine query on a multivector column). |
**Thresholding with `distance_range`:**
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexDistanceRange}
</CodeBlock>
</CodeGroup>
**Measuring recall with `bypass_vector_index`:**
Compare ANN results against a flat-scan ground truth to compute recall@k. This is the standard way to pick `nprobes` for your workload.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBypassRecall}
</CodeBlock>
</CodeGroup>
<Warning>
Flat search is $O(n)$ — reserve `bypass_vector_index()` for sampled recall measurements or small tables, not production queries.
</Warning>
<Note title="Multivector distance constraint">
Multivector indexing currently requires `distance_type="cosine"` — `l2` is rejected at index-creation time. That restriction is why `bypass_vector_index()` is the escape hatch for non-cosine queries on a multivector column: the metric you want at query time cannot be served by the index, so you fall back to a flat scan. See [Multivector Search](/search/vector-search) for the full rules.
</Note>
## Example: Construct an HNSW Index {#example-construct-an-hnsw-index}
### Index Configuration {#index-configuration-2}
There are four key parameters to set when constructing an HNSW index:
- `index_type`: choose `IVF_HNSW_SQ` for a strong recall/latency/size trade-off, or `IVF_HNSW_FLAT` when you want the IVF+HNSW structure without vector quantization.
- `metric`: The default is `l2` euclidean distance metric. Other available are `dot` and `cosine`.
- `m`: The number of neighbors to select for each vector in the HNSW graph.
- `ef_construction`: The number of candidates to evaluate during the construction of the HNSW graph.
### 1\. Construct an HNSW Index {#1-construct-an-hnsw-index}
The snippet below uses `IVF_HNSW_SQ`. If you want the unquantized variant, change `index_type` to `IVF_HNSW_FLAT`.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBuildHnsw}
</CodeBlock>
</CodeGroup>
### 2\. Query the HNSW Index {#2-query-the-hnsw-index}
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexQueryHnsw}
</CodeBlock>
</CodeGroup>
## Example: Construct a Binary Vector Index {#example-construct-a-binary-vector-index}
Binary vectors are useful for hash-based retrieval, fingerprinting, or any scenario where data can be represented as bits.
### Index Configuration {#index-configuration-3}
- Store binary vectors as fixed-size binary data (uint8 arrays, with 8 bits per byte). For storage, pack binary vectors into bytes to save space.
- Index Type: `IVF_FLAT` is used for indexing binary vectors
- `metric`: the `hamming` distance is used for similarity search
- The dimension of binary vectors must be a multiple of 8. For example, a 128-dimensional vector is stored as a uint8 array of size 16.
<Warning>
**`IVF_FLAT` + `hamming` is the only supported path for binary vectors.**
- `hamming` distance is only valid on packed binary (uint8) data; it is rejected on float vector columns.
- Quantized index types (`IVF_PQ`, `IVF_RQ`, `IVF_SQ`, `IVF_HNSW_PQ`, `IVF_HNSW_SQ`) do not accept binary inputs — their `distance_type` is restricted to `l2`, `cosine`, or `dot`.
</Warning>
### 1\. Create Table and Schema {#1-create-table-and-schema}
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBinarySchema}
</CodeBlock>
</CodeGroup>
### 2\. Generate and Add Data {#2-generate-and-add-data}
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBinaryAddData}
</CodeBlock>
</CodeGroup>
### 3\. Construct the Binary Index {#3-construct-the-binary-index}
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBinaryBuildIndex}
</CodeBlock>
</CodeGroup>
### 4\. Vector Search {#4-vector-search}
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexBinarySearch}
</CodeBlock>
</CodeGroup>
## Check Index Status {#check-index-status}
Vector index creation runs in the background and may take some time to complete. While it is ongoing, you can check its status either programmatically through the API or from the **LanceDB Enterprise UI**.
In the LanceDB Enterprise UI, navigate to your table page - the "Index" column reflects each column's index status: it is blank when no index exists, shows an "in progress" label while the index is being built, and shows the index type once the build completes.
Programmatically, use `list_indices()` and `index_stats()`. **By default**, the index name is formed by appending `_idx` to the column name (e.g., a `keywords_embeddings` column produces `keywords_embeddings_idx`). Note that `list_indices()` only returns information after the index is fully built.
To wait until all data is fully indexed, you can specify the `wait_timeout` parameter on `create_index()` or call `wait_for_index()` on the table.
Each entry returned by `list_indices()` also carries detailed per-index metadata, so you can inspect an index without a follow-up `index_stats()` call. Node.js exposes the same fields in camelCase (`num_indexed_rows` → `numIndexedRows`):
| Field | What it tells you |
| :--- | :--- |
| `num_indexed_rows`, `num_unindexed_rows` | Index coverage over the table |
| `size_bytes` | Total size of the index files on disk |
| `num_segments`, `index_version` | On-disk layout and format version |
| `created_at` | Creation time (ms since the Unix epoch in Node.js) |
| `index_uuid`, `type_url` | Internal identifiers for the index segment |
| `index_details` | Type-specific details (e.g. IVF partition counts or quantization settings) |
<Note>
These fields are populated for local and embedded tables. On LanceDB Enterprise remote tables they are returned as `None` / `undefined` until the server response surfaces them.
</Note>
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexCheckStatus}
</CodeBlock>
</CodeGroup>
## Custom Index Names {#custom-index-names}
The `{column}_idx` suffix is a default convention, not the only supported naming path. Pass `name=...` to `create_index()` to override it — useful when you want to manage multiple indexes on the same column (for example, side-by-side `IVF_PQ` and `IVF_HNSW_SQ` builds) or when you script index replacement by name. Once set, `list_indices()`, `index_stats(name)`, and `wait_for_index([name])` all reference the custom name.
<CodeGroup>
<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexCustomName}
</CodeBlock>
</CodeGroup>
Quantization compresses high-dimensional float vectors into a smaller, approximate representation, where instead of storing every vector as a float32 or float64, it's stored in compressed form, without too much of a compromise in search quality.
Use quantization when:
- You have a large dataset with relatively high-dimensional vectors (512, 768, 1024+)
- Index build time and query latency matter
LanceDB currently exposes multiple quantized vector index types, including:
- `IVF_PQ` -- Inverted File index with Product Quantization (default). See the [vector indexing guide](/indexing/vector-index) for `IVF_PQ` examples.
- `IVF_SQ` -- Inverted File index with Scalar Quantization. This is available in Python and Rust; TypeScript does not currently expose `IvfSq`.
- `IVF_RQ` -- Inverted File index with **RaBitQ** quantization (binary, 1 bit per dimension). Requires vector dimensions divisible by `8`. See [below](#rabitq-quantization) for details.
- `IVF_HNSW_SQ` -- IVF partitions with an **HNSW graph per partition** plus **Scalar Quantization**. Strong recall/latency/size trade-off for most workloads.
- `IVF_HNSW_PQ` -- IVF partitions with an **HNSW graph per partition** plus **Product Quantization**. Prefer when PQ-level compression matters and you still want HNSW-style in-partition search.
Two axes are being combined here: whether partitions are searched flatly or via an HNSW graph (`IVF_*` vs. `IVF_HNSW_*`), and which quantizer compresses the vectors (`PQ`, `RQ`, or `SQ`). `IVF_PQ` is the default and works well in many cases. For more drastic compression, RaBitQ (`IVF_RQ`) is a reasonable option. For higher recall at low latency, the HNSW-backed variants are usually the right pick. The ["Choose the Right Index"](/indexing/vector-index#choose-the-right-index) table on the vector indexing page is the canonical decision tool.
Use the same distance metric when training the index and running queries against it. For IVF-based indexes, `num_partitions` controls the number of groups and `sample_rate` controls how many training vectors are sampled per partition, so the training sample is roughly `sample_rate * num_partitions`.
## RaBitQ quantization {#rabitq-quantization}
RaBitQ is a binary quantization method that represents each normalized embedding using **1 bit per dimension**, plus a couple of small corrective scalars. In practice, a 1,024-dimensional `float32` vector that would normally take 4 KB can be compressed to roughly a few hundred bytes with RaBitQ, while still maintaining reasonable recall.
### How RaBitQ works {#how-rabitq-works}
- Embeddings are grouped around centroids (as in other IVF indexes).
- Each residual vector is normalized and mapped to the nearest vertex of a randomly rotated hypercube on the unit sphere.
- The sign pattern of that vector is stored as bits (1 bit per dimension).
- Two small corrective factors are stored:
1. The distance from the original vector to its centroid
2. The dot product between the normalized vector and its quantized version
Compared to `IVF_PQ`, RaBitQ:
- Avoids training expensive PQ codebooks
- Builds indexes faster and handles updates more easily
- Maintains or improves recall at high dimensionality under the same storage budget
For a deeper dive into the theory and some benchmark results, see the blog post: [LanceDB's RaBitQ Quantization for Blazing Fast Vector Search](https://lancedb.com/blog/feature-rabitq-quantization/).
### Using RaBitQ {#using-rabitq}
You can create an RaBitQ-backed vector index by setting `index_type="IVF_RQ"` when calling `create_index`.
<Note title="Dimension requirement">
When using `IVF_RQ`, vector dimensions must be divisible by `8`.
</Note>
`num_bits` controls how many bits per dimension are used:
1 bit is the classic RaBitQ setting. You can set it to 2, 4, or 8 bits to improve fidelity for better precision or recall — the main trade-off is additional storage for the extra bits per dimension, with only a modest increase in query-time compute.
It's also possible to tune the number of IVF partitions in `IVF_RQ`, similar to how you would do in `IVF_PQ`.
<Warning title="Reading multi-bit indexes across versions">
Indexes built with `num_bits >= 2` use an updated on-disk layout. Older LanceDB versions cannot read them and will fail with a clear missing-column error rather than returning incorrect results. Existing indexes keep working and upgrade automatically when they are rewritten (for example, during compaction, optimize, or remap). `num_bits=1` indexes are unaffected in both directions.
</Warning>
## API Reference {#api-reference}
The full list of parameters to the algorithm are listed below.
- `distance_type`: Literal["l2", "cosine", "dot"], defaults to "l2"
The distance metric to use for similarity comparison. Choose "l2" for Euclidean, "cosine" for cosine similarity, or "dot" for dot product.
- `num_partitions`: Optional[int], defaults to None
Number of IVF partitions (affects index build time and query accuracy). More partitions can improve recall but may increase build time. When unset, LanceDB chooses roughly the square root of the row count.
- `num_bits`: int, defaults to 1
Bits per dimension for quantization (1 is standard RaBitQ). Higher values improve fidelity, mainly at the cost of additional storage.
- `max_iterations`: int, defaults to 50
Maximum number of iterations for training the quantizer. Increase for larger datasets or to improve quantization quality.
- `sample_rate`: int, defaults to 256
Number of samples per partition during training. Higher values may improve accuracy but increase training time.
- `target_partition_size`: Optional[int], defaults to None
Target number of vectors per partition. Adjust to control partition granularity and memory usage. If `num_partitions` is also set, `num_partitions` takes precedence.