title_wip

The default values of all HNSW-specific parameters work reasonably well in the majority of use cases.
We therefore do not recommend customizing the HNSW-specific parameters.

Further restrictions apply:

- Vector similarity indexes can only be build on columns of type [Array(Float32)](/docs/sql-reference/data-types/array), [Array(Float64)](/docs/sql-reference/data-types/array), or [Array(BFloat16)](/docs/sql-reference/data-types/array). Arrays of nullable and low-cardinality floats such as `Array(Nullable(Float32))` and `Array(LowCardinality(Float32))` are not allowed.
- Vector similarity indexes must be build on single columns.
- Vector similarity indexes may be build on calculated expressions (e.g., `INDEX index_name arraySort(vectors) TYPE vector_similarity([...])`) but such indexes cannot be used for approximate neighbor search later on.
- Vector similarity indexes require that all arrays in the underlying column have `<dimension>`-many elements - this is checked during index creation. To detect violations of this requirement as early as possible, users can add a [constraint](/docs/sql-reference/statements/create/table#constraints) for the vector column, e.g., `CONSTRAINT same_length CHECK length(vectors) = 256`.
- Likewise, array values in the underlying column must not be empty (`[]`) or have a default value (also `[]`).

**Estimating storage and memory consumption**

A vector generated for use with a typical AI model (e.g. a Large Language Model, [LLMs](https://en.wikipedia.org/wiki/Large_language_model)) consists of hundreds or thousands of floating-point values.
Thus, a single vector value can have a memory consumption of multiple kilobyte.
Users who like to estimate the storage required for the underlying vector column in the table, as well as the main memory needed for the vector similarity index, can use below two formula:

Storage consumption of the vector column in the table (uncompressed):

```
Storage consumption = Number of vectors * Dimension * Size of column data type
```

Example for the [dbpedia dataset](https://huggingface.co/datasets/KShivendu/dbpedia-entities-openai-1M):

```
Storage consumption = 1 million * 1536 * 4 (for Float32) = 6.1 GB
```

The vector similarity index must be fully loaded from disk into main memory to perform searches.
Similarly, the vector index is also constructed fully in memory and then saved to disk.

Memory consumption required to load a vector index:

```
Memory for vectors in the index (mv) = Number of vectors * Dimension * Size of quantized data type
Memory for in-memory graph (mg) = Number of vectors * hnsw_max_connections_per_layer * Bytes_per_node_id (= 4) * Layer_node_repetition_factor (= 2)

Memory consumption: mv + mg
```

Example for the [dbpedia dataset](https://huggingface.co/datasets/KShivendu/dbpedia-entities-openai-1M):

```
Memory for vectors in the index (mv) = 1 million * 1536 * 2 (for BFloat16) = 3072 MB
Memory for in-memory graph (mg) = 1 million * 64 * 2 * 4 = 512 MB

Memory consumption = 3072 + 512 = 3584 MB
```

Above formula does not account for additional memory required by vector similarity indexes to allocate runtime data structures like pre-allocated buffers and caches.

#### Using a Vector Similarity Index[​](#using-a-vector-similarity-index "Direct link to Using a Vector Similarity Index")

Note

To use vector similarity indexes, setting [compatibility](/docs/operations/settings/settings) has be `''` (the default value), or `'25.1'` or newer.

Vector similarity indexes support SELECT queries of this form:

```
WITH [...] AS reference_vector
SELECT [...]
FROM table
WHERE [...] -- a WHERE clause is optional
ORDER BY <DistanceFunction>(vectors, reference_vector)
LIMIT <N>
```

ClickHouse's query optimizer tries to match above query template and make use of available vector similarity indexes.
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.

Advanced users may provide a custom value for setting [hnsw\_candidate\_list\_size\_for\_search](/docs/operations/settings/settings#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>`).
The default value of the setting 256 works well in the majority of use cases.
Higher setting values mean better accuracy at the cost of slower performance.

If the query can use a vector similarity index, ClickHouse checks that the LIMIT `<N>` provided in SELECT queries is within reasonable bounds.
More specifically, an error is returned if `<N>` is bigger than the value of setting [max\_limit\_for\_vector\_search\_queries](/docs/operations/settings/settings#max_limit_for_vector_search_queries) with default value 100.
Too large LIMIT values can slow down searches and usually indicate a usage error.

To check if a SELECT query uses a vector similarity index, you can prefix the query with `EXPLAIN indexes = 1`.

As an example, query

```
EXPLAIN indexes = 1
WITH [0.462, 0.084, ..., -0.110] AS reference_vec
SELECT id, vec
FROM tab
ORDER BY L2Distance(vec, reference_vec) ASC
LIMIT 10;
```

may return

```
    ┌─explain─────────────────────────────────────────────────────────────────────────────────────────┐
 1. │ Expression (Project names)                                                                      │
 2. │   Limit (preliminary LIMIT (without OFFSET))                                                    │
 3. │     Sorting (Sorting for ORDER BY)                                                              │
 4. │       Expression ((Before ORDER BY + (Projection + Change column names to column identifiers))) │
 5. │         ReadFromMergeTree (default.tab)                                                         │
 6. │         Indexes:                                                                                │
 7. │           PrimaryKey                                                                            │
 8. │             Condition: true                                                                     │
 9. │             Parts: 1/1                                                                          │
10. │             Granules: 575/575                                                                   │
11. │           Skip                                                                                  │
12. │             Name: idx                                                                           │
13. │             Description: vector_similarity GRANULARITY 100000000                                │
14. │             Parts: 1/1                                                                          │
15. │             Granules: 10/575                                                                    │
    └─────────────────────────────────────────────────────────────────────────────────────────────────┘
```

In this example, 1 million vectors in the [dbpedia dataset](https://huggingface.co/datasets/KShivendu/dbpedia-entities-openai-1M), each with dimension 1536, are stored in 575 granules, i.e. 1.7k rows per granule.
The query asks for 10 neighbours and the vector similarity index finds these 10 neighbours in 10 separate granules.
These 10 granules will be read during query execution.

Vector similarity indexes are used if the output contains `Skip` and the name and type of the vector index (in the example, `idx` and `vector_similarity`).
In this case, the vector similarity index dropped two of four granules, i.e. 50% of the data.
The more granules can be dropped, the more effective index usage becomes.

Tip

To enforce index usage, you can run the SELECT query with setting [force\_data\_skipping\_indexes](/docs/operations/settings/settings#force_data_skipping_indices) (provide the index name as setting value).

**Post-filtering and Pre-filtering**