Skip to content

Update indexing and quantization docs - #344

Merged
westonpace merged 52 commits into
mainfrom
update-indexing-docs
Sep 11, 2026
Merged

Update indexing and quantization docs#344
westonpace merged 52 commits into
mainfrom
update-indexing-docs

Conversation

@jzheng106

Copy link
Copy Markdown
Contributor

Substantial changes to indexing documentation, as part of Jason's internship project. Reorganized and rewrote "overview", "vector index", and "quantization" tabs in https://docs.lancedb.com/indexing . Added descriptions of algorithms and improved API references, usage examples, and overall readability/flow. Msg me on slack with questions

Comment thread docs/indexing/index.mdx
| `SQ` (Scalar Quantization) | Use when you need faster indexing or when vector dimensions have consistent value ranges. | Quantizes each dimension independently. Simpler than PQ but typically provides less compression. |
| `RQ` (RabitQ Quantization) | Use when you need maximum compression or have specific per-dimension requirements. | Per-dimension quantization using a RabitQ codebook. Provides fine-grained control over compression per dimension. For `IVF_RQ`, vector dimensions must be divisible by `8`. |
| `SQ` (Scalar Quantization) | Use when you need faster indexing or when vector dimensions have consistent value ranges. | Quantizes each dimension independently. Simpler than PQ but typically provides less compression. |
| `None/Flat` | Use for binary vectors (with `hamming` distance) or when you need maximum recall and have sufficient storage. | No quantization—stores raw vectors. Provides the highest accuracy but requires more storage and memory. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm not sure if changing this was in scope, but I find these descriptions pretty weak. They would be better if they gave some kind of comparison between each other. For example if we are saying these are all useful because they fall at different points on the compression/speed/accuracy plane, we should describe how they actually relate. Why would I choose PQ over RQ, or SQ over PQ, is not really answered by this table.

Another way to do this is something like,

If you need X [petabyte scale low-latency search on static dataset], choose Y because x, y, z
If you need A, choose B because a, b, c

etc. I have no idea what the real values to plug in here are though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

"I think these descriptions are pretty weak" I agree. Unfortunately, until recently many technical descriptions were written similar to this, and I didn't really know how to approach them (I also didn't have a clearly defined scope for this documentation task) so I just largely took my best guess. I agree that there could be further improvements. Maybe I'll make a note of this and add it to a future commit?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the Use Case column makes a stab at this doesn't it? I don't know if it reflects reality though. I read it as...

PQ is the baseline.
RQ achieves better compression than PQ with minimal loss to accuracy.
SQ sacrifices compression but can speed up index builds
Flat discards compression entirely in favor of accuracy

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think the use cases don't do it for me because they don't compare all the options on the same plane. How do I compare (fast indexing, consistent value ranges) to (max compression, particular dimension requirements). Assuming I am reading the right column.

Comment thread out.txt Outdated
@@ -0,0 +1,172 @@
9f362963 docs/user-guides/indexing/index.mdx (erik-wang-lancedb 2025-11-30 21:12:29 -0800 1) ---

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

is this included intentionally?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

no. oops. you're right to delete the whole file

@westonpace westonpace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for working on this. I think this PR improves things but we can still improve further, especially for a naive user.

We've also removed a lot of information. I think that can be good to focus the guide. I'll try and do a second pass soon to see if we removed anything that might have been important.

Comment thread docs/indexing/scalar-index.mdx Outdated
Comment thread docs/indexing/index.mdx
Comment thread docs/indexing/index.mdx
| `SQ` (Scalar Quantization) | Use when you need faster indexing or when vector dimensions have consistent value ranges. | Quantizes each dimension independently. Simpler than PQ but typically provides less compression. |
| `RQ` (RabitQ Quantization) | Use when you need maximum compression or have specific per-dimension requirements. | Per-dimension quantization using a RabitQ codebook. Provides fine-grained control over compression per dimension. For `IVF_RQ`, vector dimensions must be divisible by `8`. |
| `SQ` (Scalar Quantization) | Use when you need faster indexing or when vector dimensions have consistent value ranges. | Quantizes each dimension independently. Simpler than PQ but typically provides less compression. |
| `None/Flat` | Use for binary vectors (with `hamming` distance) or when you need maximum recall and have sufficient storage. | No quantization—stores raw vectors. Provides the highest accuracy but requires more storage and memory. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the Use Case column makes a stab at this doesn't it? I don't know if it reflects reality though. I read it as...

PQ is the baseline.
RQ achieves better compression than PQ with minimal loss to accuracy.
SQ sacrifices compression but can speed up index builds
Flat discards compression entirely in favor of accuracy

Comment thread docs/indexing/quantization.mdx Outdated
Comment thread docs/indexing/quantization.mdx
**Using `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.
Use `bypass_vector_index` to compute an exact **kNN** result. Note that exact queries may be prohibitively slow on production scales.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we discuss recall@k anywhere anymore?

I think "how do I know if my vector index is properly configured" or "how do I know how well my vector index is performing" is a common question we should be answering on this page. I'm not sure the old page answered it well either but I think we should strive to include that somewhere (and calculating recall@k is part of the answer)

Comment thread docs/indexing/vector-index.mdx Outdated
Comment thread docs/indexing/vector-index.mdx Outdated
</Warning>
| Parameter | Description |
| :--- | :--- |
| `m` | The number of neighbors to select for each vector in the HNSW graph. |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we have any guidance on this parameter? What is the default?

Comment thread docs/indexing/vector-index.mdx

@westonpace westonpace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In this pass I did a look for anything we might be missing in this conversion. There's a few things I think it would be nice to keep.

Comment thread docs/indexing/vector-index.mdx
Comment thread docs/snippets/indexing.mdx Outdated
Comment thread docs/snippets/indexing.mdx Outdated
Comment thread docs/snippets/indexing.mdx Outdated
Comment thread docs/indexing/index.mdx

For vector indexes, use the same distance metric when creating the index and searching it. After appends or other writes, use `optimize()` to fold new rows into existing indexes, then check `index_stats(...)` or `wait_for_index(...)` if you need to confirm the index has caught up. `wait_for_index(...)` waits until the named indexes exist and report `num_unindexed_rows == 0`; it can time out if writes keep adding unindexed rows.

By default, automatic vector indexing creates `IVF_PQ`, and scalar index creation defaults to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

use the same distance metric when creating the index and searching it

This part is important and probably something we should highlight (I don't think the new version says this at all).

If the user creates a vector index with (for example) cosine distance and then they search the vector distance with l2 then we will silently fallback to a full scan (without the index) which is surprising and costly. It's led to complaints from users on more than one occasion.

I'd argue it is a bug (we should fail unless bypass_vector_index is specified), but it is one we seem determined not to fix.

The user must either specify the same distance type that was used to train the index or they must not speciy distance type at all.

Can we add that guidance into the docs somewhere?

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think the new docs explain that you can replace existing indexes

<CodeBlock filename="Python" language="Python" icon="python">
{VectorIndexNestedField}
</CodeBlock>
</CodeGroup>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we still have an example of a nested field somewhere?

Comment thread docs/indexing/quantization.mdx Outdated
Comment thread docs/indexing/vector-index.mdx Outdated
jzheng106 and others added 17 commits September 11, 2026 06:06
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
Co-authored-by: Weston Pace <weston.pace@gmail.com>
@westonpace
westonpace merged commit db47318 into main Sep 11, 2026
4 checks passed
@westonpace
westonpace deleted the update-indexing-docs branch September 11, 2026 20:02
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.

3 participants