# Zvec Index Types: Supported Indexes and Performance Trade-offs in Alibaba Zvec

> Explore Zvec index types: Flat, IVF, HNSW, and Invert. Understand their performance trade-offs in query latency, memory, and recall for your Alibaba Zvec implementation.

- Repository: [Alibaba/zvec](https://github.com/alibaba/zvec)
- Tags: deep-dive
- Published: 2026-02-16

---

**Zvec supports four index types—Flat (exact), IVF (inverted file), HNSW (graph-based), and Invert (scalar)—each offering distinct trade-offs between query latency, memory overhead, and recall accuracy.**

The `alibaba/zvec` repository provides a high-performance vector database engine with pluggable indexing strategies. Understanding the available **zvec index types** and their implementation details is essential for optimizing search performance across different data scales and accuracy requirements.

## Supported Zvec Index Types

### Flat Index (Exact Search)

The **Flat** index performs a brute-force scan of all vectors without building auxiliary data structures. Defined in [`src/include/zvec/core/interface/index_param.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/core/interface/index_param.h) (lines 56-64), this index type stores raw vectors sequentially and computes exact distances during query time.

Use Flat indexes when your dataset fits in memory and you require 100% recall. The trade-off is linear query complexity **O(N·D)**, making it unsuitable for large collections.

### IVF Index (Inverted File)

The **IVF** (Inverted File) index implements a two-level quantization strategy. As defined in [`src/include/zvec/db/type.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/type.h) (lines 23-29), IVF partitions the vector space into `nlist` coarse cells using a quantizer. Each cell maintains an inverted list of vector IDs belonging to that partition.

Query performance depends on the `nprobe` parameter—the number of cells to probe during search. Higher `nprobe` values improve recall at the cost of increased latency. IVF offers a balanced speed-vs-accuracy trade-off for medium-to-large static collections.

### HNSW Index (Hierarchical Navigable Small World)

The **HNSW** index constructs a multi-layer proximity graph for approximate nearest neighbor (ANN) search. Also defined in [`src/include/zvec/db/type.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/type.h), HNSW provides logarithmic query complexity with parameters `M` (graph connectivity), `ef_construction` (build-time quality), and `ef_search` (query-time quality).

HNSW excels at large-scale, high-recall workloads and supports dynamic inserts and deletes without full index rebuilds. Memory overhead is moderate—typically 2-4× the raw vector size due to graph edge storage.

### Invert Index (Scalar Fields)

The **INVERT** index handles non-vector data types (strings, numbers, arrays) for the SQL query engine. Defined alongside IVF and HNSW in [`src/include/zvec/db/type.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/type.h), this index enables exact-match filtering and join operations on scalar columns.

Invert indexes are essential for hybrid queries that combine vector similarity search with structured predicates.

## Performance Trade-offs and Selection Guide

| Index | Build Cost | Memory Overhead | Query Latency | Recall | Update Support |
|-------|------------|----------------|---------------|---------|----------------|
| **Flat** | **O(N·D)** – stores raw vectors only | Minimal (raw vectors) | Linear **O(N·D)** | **100%** (exact) | Trivial append-only |
| **IVF** | **O(N·D)** for quantizer training + assignment | ~0.5-1× raw size (centroids + lists) | Sub-linear (*nprobe* × avg list size) | Tunable via *nprobe* | Rebuild or incremental add |
| **HNSW** | Higher (graph construction with *M*, *ef_construction*) | ~2-4× raw size (graph edges) | Logarithmic **O(log N)** with *ef_search* | >95% typical; tunable via *ef_search* | Fully dynamic (add/remove) |
| **INVERT** | Negligible (hash/bitmap) | Depends on cardinality; usually << vector storage | O(1) exact match | Exact (deterministic) | Efficient insert/delete |

### When to Choose Each Index

*   **Flat**: Use for small collections (<100k vectors) or when exact results are mandatory.
*   **IVF**: Select for medium-to-large static datasets where you need configurable recall without the memory overhead of graph structures.
*   **HNSW**: Choose for large-scale, high-throughput ANN workloads requiring dynamic updates and sub-millisecond latency.
*   **INVERT**: Deploy for SQL filtering on metadata fields, typically in conjunction with vector indexes for hybrid search.

## Implementation Details and Key Files

The `IndexType` enum in [`src/include/zvec/core/interface/index_param.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/core/interface/index_param.h) defines the vector index types (`kFlat`, `kIVF`, `kHNSW`) available to the **IndexFactory**. The broader `IndexType` enum in [`src/include/zvec/db/type.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/type.h) extends this set to include `INVERT` for scalar fields.

`IndexFactory::CreateAndInitIndex` (implemented in `src/core/interface/index_factory.cc`, lines 41-48) instantiates the concrete implementations: `FlatIndex`, `IVFIndex`, and `HNSWIndex`. These classes inherit from the abstract `Index` interface defined in [`src/include/zvec/core/interface/index.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/core/interface/index.h).

Parameter structures for each index type reside in [`src/include/zvec/db/index_params.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/index_params.h), while the Python bindings in [`python/zvec/zvec.py`](https://github.com/alibaba/zvec/blob/main/python/zvec/zvec.py) expose these configurations via JSON serialization.

## Code Examples

### Flat Index (C++)

```cpp
#include <zvec/core/interface/index_factory.h>
#include <zvec/core/interface/index_param_builders.h>
using namespace zvec::core_interface;

auto flat_param = FlatIndexParamBuilder()
                      .WithVersion(1)
                      .WithIndexType(IndexType::kFlat)
                      .WithMetricType(MetricType::kInnerProduct)
                      .WithDimension(128)
                      .Build();

auto flat_idx = IndexFactory::CreateAndInitIndex(*flat_param);

```

### IVF Index (C++)

```cpp
auto ivf_param = IVFIndexParamBuilder()
                     .WithVersion(1)
                     .WithIndexType(IndexType::kIVF)
                     .WithMetricType(MetricType::kCosine)
                     .WithDimension(128)
                     .WithNList(1024)          // coarse centroids
                     .Build();

auto ivf_idx = IndexFactory::CreateAndInitIndex(*ivf_param);

// Query-time parameter
IVFQueryParam query;
query.nprobe = 16;           // cells to probe

```

### HNSW Index (C++)

```cpp
auto hnsw_param = HNSWIndexParamBuilder()
                      .WithVersion(1)
                      .WithIndexType(IndexType::kHNSW)
                      .WithMetricType(MetricType::kL2)   // Euclidean
                      .WithDimension(128)
                      .WithM(16)                         // graph connectivity
                      .WithEFConstruction(200)           // build quality
                      .Build();

auto hnsw_idx = IndexFactory::CreateAndInitIndex(*hnsw_param);

// Search parameter
HNSWQueryParam qp;
qp.ef_search = 100;         // higher = better recall, slower

```

### Inverted Index (C++)

```cpp
auto invert_param = IndexParams(IndexType::INVERT);   // scalar index
auto invert_idx  = IndexFactory::CreateAndInitIndex(invert_param);

```

### Python Configuration (JSON)

```python
import zvec

json_str = """
{
  "index_type": "kIVF",
  "metric_type": "kCosine",
  "dimension": 128,
  "nlist": 1024
}
"""

param = zvec.IndexParam.from_json(json_str)
index = zvec.IndexFactory.create_and_init(param)

```

## Summary

*   **Zvec index types** include **Flat** (exact brute-force), **IVF** (inverted file with coarse quantization), **HNSW** (proximity graph for ANN), and **INVERT** (scalar field indexing).
*   **Flat** guarantees 100% recall with linear scan latency; choose it for small datasets or exact requirements.
*   **IVF** offers tunable speed-vs-recall via `nlist` and `nprobe` parameters; ideal for medium-scale static collections.
*   **HNSW** provides logarithmic query complexity and dynamic updates via graph parameters `M`, `ef_construction`, and `ef_search`; best for large-scale, high-throughput ANN workloads.
*   **INVERT** handles non-vector data for SQL filtering and hybrid search scenarios.
*   Implementation resides in [`src/include/zvec/core/interface/index_param.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/core/interface/index_param.h), [`src/include/zvec/db/type.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/db/type.h), and `src/core/interface/index_factory.cc`.

## Frequently Asked Questions

### What is the difference between Flat and HNSW indexes in zvec?

**Flat** performs an exhaustive brute-force scan of all vectors, guaranteeing exact results (100% recall) but with **O(N·D)** query complexity. **HNSW** constructs a multi-layer proximity graph that enables approximate nearest neighbor search with **O(log N)** complexity, trading a small accuracy margin (typically >95% recall) for orders-of-magnitude faster queries on large datasets.

### When should I use IVF instead of HNSW for vector search?

Choose **IVF** when you have medium-to-large static collections where you need a configurable balance between build cost and query performance without the memory overhead of graph structures. IVF is often preferred when you can tolerate occasional index rebuilds and want to tune recall via the `nprobe` parameter. Select **HNSW** when you require dynamic updates without rebuilding, or when you need the lowest possible latency on billion-scale datasets.

### Does zvec support dynamic updates to HNSW indexes?

Yes, according to the implementation in [`src/include/zvec/core/interface/index.h`](https://github.com/alibaba/zvec/blob/main/src/include/zvec/core/interface/index.h) and `src/core/interface/index_factory.cc`, **HNSW** indexes support fully dynamic operations. You can add or remove vectors without triggering a full index rebuild, making HNSW suitable for online serving scenarios with frequent data changes. This contrasts with **IVF** indexes, which typically require re-assignment to centroids or partial rebuilds for optimal performance after significant updates.

### How do I configure the nprobe parameter for IVF indexes in zvec?

The `nprobe` parameter controls the number of inverted lists to scan during query execution. In C++, set it via the `IVFQueryParam` structure after building the index:

```cpp
IVFQueryParam query;
query.nprobe = 16;  // Trade-off: higher values improve recall but increase latency

```

Higher `nprobe` values improve recall by examining more candidate cells but linearly increase query time. For most applications, start with `nprobe` set to 5-10% of your `nlist` value and tune based on your specific recall requirements.