You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/en/engines/table-engines/mergetree-family/annindexes.md
+65-18Lines changed: 65 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,7 +78,7 @@ ClickHouse provides a special "vector similarity" index to perform approximate n
78
78
:::note
79
79
Vector similarity indexes are currently experimental.
80
80
To enable them, please first run `SET allow_experimental_vector_similarity_index = 1`.
81
-
If you run into problems, kindly open an issue at github.com/clickhouse/clickhouse/issues.
81
+
If you run into problems, kindly open an issue in the [ClickHouse repository](https://github.com/clickhouse/clickhouse/issues).
82
82
:::
83
83
84
84
### Creating a Vector Similarity Index {#creating-a-vector-similarity-index}
@@ -174,13 +174,13 @@ LIMIT <N>
174
174
ClickHouse's query optimizer tries to match above query template and make use of available vector similarity indexes.
175
175
A query can only use a vector similarity index if the distance function in the SELECT query is the same as the distance function in the index definition.
176
176
177
-
Advanced users may provide a custom value for setting [hnsw_candidate_list_size_for_search](../../../operations/settings/settings.md#hnsw_candidate_list_size_for_search) (also know as HNSW hyperparameter `ef_search`) to tune the size of the candidate list during search (e.g. `SELECT [...] SETTINGS hnsw_candidate_list_size_for_search = <value>`).
177
+
Advanced users may provide a custom value for setting [hnsw_candidate_list_size_for_search](../../../operations/settings/settings.md#hnsw_candidate_list_size_for_search) (also know as HNSW hyperparameter "ef_search") to tune the size of the candidate list during search (e.g. `SELECT [...] SETTINGS hnsw_candidate_list_size_for_search = <value>`).
178
178
The default value of the setting 256 works well in the majority of use cases.
179
179
Higher setting values mean better accuracy at the cost of slower performance.
180
180
181
181
If the query can use a vector similarity index, ClickHouse checks that the LIMIT `<N>` provided in SELECT queries is within reasonable bounds.
182
182
More specifically, an error is returned if `<N>` is bigger than the value of setting [max_limit_for_vector_search_queries](../../../operations/settings/settings.md#max_limit_for_vector_search_queries) with default value 100.
183
-
Too large LIMITs can slow down searches and usually indicate a usage error.
183
+
Too large LIMIT values can slow down searches and usually indicate a usage error.
184
184
185
185
To check if a SELECT query uses a vector similarity index, you can prefix the query with `EXPLAIN indexes = 1`.
186
186
@@ -231,23 +231,22 @@ To enforce index usage, you can run the SELECT query with setting [force_data_sk
231
231
232
232
**Post-filtering and Pre-filtering**
233
233
234
-
Users may optionally specify a `WHERE` clause with additional filter conditions in SELECT queries.
235
-
Depending on these filter conditions, ClickHouse will utilize post-filtering or pre-filtering.
236
-
These two strategies determine the order in which the filters are evaluated:
237
-
-With post-filtering, the vector similarity index is evaluated first, afterwards ClickHouse evaluates the additional filter(s) specified of the `WHERE` clause.
238
-
-With pre-filtering, the filter evaluation order is the other way round.
234
+
Users may optionally specify a `WHERE` clause with additional filter conditions for the SELECT query.
235
+
ClickHouse will evaluate these filter conditions using post-filtering or pre-filtering strategy.
236
+
In short, both strategies determine the order in which the filters are evaluated:
237
+
-Post-filtering means that the vector similarity index is evaluated first, afterwards ClickHouse evaluates the additional filter(s) specified in the `WHERE` clause.
238
+
-Pre-filtering means that the filter evaluation order is the other way round.
239
239
240
-
Both strategies have different trade-offs:
241
-
- Post-filtering has the general problem that it may return less than the number of rows requested in the `LIMIT <N>` clause. This happens when at least one of the result rows returned by the vector similarity index fails to satisfy the additional filters. In ClickHouse, this situation is luckily unlikely to happen because vector similarity indexes do not return rows but blocks with thousands of rows (see "Differences to Regular Skipping Indexes" below).
242
-
- Pre-filtering is an unsolved problem. Some specialized vector databases implement it but most databases including ClickHouse will fall back to exact neighbor search, i.e., a brute-force scan without index.
240
+
The strategies have different trade-offs:
241
+
- Post-filtering has the general problem that it may return less than the number of rows requested in the `LIMIT <N>` clause. This situation happens when one or more result rows returned by the vector similarity index fails to satisfy the additional filters.
242
+
- Pre-filtering is generally an unsolved problem. Certain specialized vector databases provide pre-filtering algorithms but most relational databases (including ClickHouse) will fall back to exact neighbor search, i.e., a brute-force scan without index.
243
243
244
-
What strategy is used comes down to whether ClickHouse can use indexes for the additional filter conditions.
244
+
What strategy is used depends on the filter condition.
245
245
246
-
If no index can be used, post-filtering will be applied.
246
+
*Additional filters are part of the partition key*
247
247
248
248
If the additional filter condition is part of the partition key, then ClickHouse will apply partition pruning.
249
-
250
-
Example, assuming that the table is range-partitioned by `year`:
249
+
As an example, a table is range-partitioned by column `year` and the following query is run:
251
250
252
251
```sql
253
252
WITH [0., 2.] AS reference_vec
@@ -258,10 +257,58 @@ ORDER BY L2Distance(vec, reference_vec) ASC
258
257
LIMIT3;
259
258
```
260
259
261
-
ClickHouse will ignore all partitions but the one for year 2025.
262
-
Within this partition, a post-filtering strategy will be applied.
260
+
ClickHouse will prune all partitions except the 2025 one.
261
+
262
+
*Additional filters cannot be evaluated using indexes*
263
+
264
+
If additional filter conditions cannot be evaluated using indexes (primary key index, skipping index), ClickHouse will apply post-filtering.
265
+
266
+
*Additional filters can be evaluated using the primary key index*
267
+
268
+
If additional filter conditions can be evaluated using the [primary key](mergetree.md#primary-key) (i.e., they form a prefix of the primary key) and
269
+
- the filter condition eliminates at least one row within a part, the ClickHouse will fall back to pre-filtering for the "surviving" ranges within the part,
270
+
- the filter condition eliminates no rows within a part, the ClickHouse will perform post-filtering for the part.
271
+
272
+
In practical use cases, the latter case is rather unlikely.
273
+
274
+
*Additional filters can be evaluated using skipping index*
275
+
276
+
If additional filter conditions can be evaluated using [skipping indexes](mergetree.md#table_engine-mergetree-data_skipping-indexes) (minmax index, set index, etc.), Clickhouse performs post-filtering.
277
+
In such cases, the vector similarity index is evaluated first as it is expected to remove the most rows relative to other skipping indexes.
278
+
279
+
For finer control over post-filtering vs. pre-filtering, two settings can be used:
280
+
281
+
Setting [vector_search_filter_strategy](../../../operations/settings/settings#vector_search_filter_strategy) (default: `auto` which implements above heuristics) may be set to `prefilter`.
282
+
This is useful to force pre-filtering in cases where the additional filter conditions are extremely selective.
283
+
As an example, the following query may benefit from pre-filtering:
284
+
285
+
```sql
286
+
SELECT bookid, author, title
287
+
FROM books
288
+
WHERE price <2.00
289
+
ORDER BY cosineDistance(book_vector, getEmbedding('Books on ancient Asian empires'))
290
+
LIMIT10
291
+
```
292
+
293
+
Assuming that only a very small number of books cost less than $2, post-filtering may return zero rows because the top 10 matches returned by the vector index could all be priced above $2.
294
+
By forcing pre-filtering (add `SETTINGS vector_search_filter_strategy = 'prefilter'` to the query), ClickHouse first finds all books with a price of less than $2 and then executes a brute-force vector search for the found books.
295
+
296
+
As an alternative approach to resolve above issue, setting [vector_search_postfilter_multiplier](../../../operations/settings/settings#vector_search_postfilter_multiplier) (default: `1.0`) may be configured to a value > `1.0` (for example, `2.0`).
297
+
The number of nearest neighbors fetched from the vector index is multiplied by the setting value and then the additional filter to be applied on those rows to return LIMIT-many rows.
298
+
As an example, we can query again but with multiplier `3.0`:
299
+
300
+
```sql
301
+
SELECT bookid, author, title
302
+
FROM books
303
+
WHERE price <2.00
304
+
ORDER BY cosineDistance(book_vector, getEmbedding('Books on ancient Asian empires'))
305
+
LIMIT10
306
+
SETTING vector_search_postfilter_multiplier =3.0;
307
+
```
263
308
264
-
If the additional filter condition is part of the primary key, then ClickHouse will always apply pre-filtering.
309
+
ClickHouse will fetch 3.0 x 10 = 30 nearest neighbors from the vector index in each part and afterwards evaluate the additional filters.
310
+
Only the ten closest neighbors will be returned.
311
+
We note that setting `vector_search_postfilter_multiplier` can mitigate the problem but in extreme cases (very selective WHERE condition), it is still possible that less than N requested rows returned.
If a vector search query has a WHERE clause, this setting determines if it is evaluated first (pre-filtering) OR if the vector similarity index is checked first (post-filtering). Possible values:
6588
+
- 'auto' - Postfiltering (the exact semantics may change in future).
6589
+
- 'postfilter' - Use vector similarity index to identify the nearest neighbours, then apply other filters
6590
+
- 'prefilter' - Evaluate other filters first, then perform brute-force search to identify neighbours.
{"vector_search_filter_strategy", "auto", "auto", "New setting"},
102
+
{"vector_search_postfilter_multiplier", 1, 1, "New setting"},
101
103
{"compile_expressions", false, true, "We believe that the LLVM infrastructure behind the JIT compiler is stable enough to enable this setting by default."},
102
104
{"use_legacy_to_time", false, false, "New setting. Allows for user to use the old function logic for toTime, which works as toTimeWithFixedDate."},
103
105
{"input_format_parquet_allow_geoparquet_parser", false, true, "A new setting to use geo columns in parquet file"},
0 commit comments