跳转至

HNSW 索引

层次化可导航小世界(Hierarchical Navigable Small World,HNSW)是 GoVector 中的默认索引类型,提供高效的近似最近邻(ANN)搜索。本文档解释 HNSW 的工作原理以及如何针对您的用例进行优化。

📋 HNSW 概述

HNSW 是一种最先进的近似最近邻搜索算法,它:

  • 提供高召回率(对于调优的参数,接近 100%)
  • 提供快速搜索性能(O(log N) 复杂度)
  • 很好地扩展到高维向量(高达数千维)
  • 支持动态插入新向量

🔧 HNSW 参数

核心参数

参数 描述 默认值 范围 影响
M 每个节点的连接数 16 4-64 值越高,准确性和内存使用越高
EfConstruction 索引构建过程中动态候选列表的大小 200 10-∞ 值越高,索引质量越好,但构建时间越长
EfSearch 搜索过程中动态候选列表的大小 10 10-∞ 值越高,召回率越好,但搜索时间越长

🚀 创建 HNSW 索引

嵌入式模式

import (
    "github.com/yourusername/govector/core"
)

// 创建带有 HNSW 索引的集合
collection, err := core.NewCollection(core.CollectionConfig{
    Name:            "my-collection",
    VectorLen:       768,
    Metric:          core.Cosine,
    IndexType:       core.HNSW,  // 使用 HNSW 索引
    M:               16,         // 每个节点的连接数
    EfConstruction:  200,        // 构建参数
    EfSearch:        10,         // 搜索参数
})
if err != nil {
    log.Fatalf("创建集合失败: %v", err)
}

微服务模式

curl -X POST http://localhost:6333/collections \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-collection",
    "vectors": {
      "size": 768,
      "distance": "Cosine"
    },
    "hnsw_config": {
      "m": 16,
      "ef_construction": 200,
      "ef": 10
    }
  }'

📊 HNSW 工作原理

HNSW 创建一个多层图结构,其中:

  1. 每一层都是一个可导航的小世界图
  2. 较高层作为较低层的粗略引导
  3. 搜索从顶层开始,向下导航以找到最近邻
  4. 插入遵循类似的路径,在每一层建立连接

搜索过程

flowchart TD
    A[从顶层开始] --> B[在当前层找到最近邻]
    B --> C{当前层是底层?}
    C -->|否| D[移动到下一层]
    D --> B
    C -->|是| E[返回最近邻]

插入过程

flowchart TD
    A[从顶层开始] --> B[在当前层找到最近邻]
    B --> C{当前层是底层?}
    C -->|否| D[移动到下一层]
    D --> B
    C -->|是| E[插入节点并建立连接]
    E --> F[可能将节点添加到更高层]

💡 优化技巧

对于大型数据集

  • 增加 M 到 24-32 以获得更高的召回率
  • 增加 EfConstruction 到 400-1000 以获得更好的索引质量
  • 使用 EfSearch 在 50-100 之间以获得高召回率应用
  • 启 SQ8 量化 以减少内存使用

对于快速搜索

  • 减少 M 到 8-12 以加快索引速度并降低内存使用
  • 设置 EfSearch 为 10-20 以加快搜索速度(以召回率为代价)
  • 尽可能使用较小的向量(例如,使用 384 维而不是 768 维)

对于内存约束

  • 启 SQ8 量化 以减少约 75% 的内存
  • 使用较小的 M 值(8-12)
  • 考虑 Flat 索引 对于非常小的数据集(< 10,000 点)

📈 性能基准

搜索性能

数据集大小 M EfSearch 召回率 QPS
100K 点 16 10 ~0.9 10,000+
100K 点 16 50 ~0.95 5,000+
100K 点 16 100 ~0.99 2,000+
1M 点 16 10 ~0.85 5,000+
1M 点 16 50 ~0.9 2,000+
1M 点 16 100 ~0.95 1,000+

内存使用

数据集大小 向量维度 M 内存(无量化) 内存(带 SQ8)
100K 点 768 16 ~1GB ~250MB
1M 点 768 16 ~10GB ~2.5GB
10M 点 768 16 ~100GB ~25GB

🚩 常见问题

索引构建缓慢

  • 原因EfConstruction 值过高或数据集过大
  • 解决方案:为数据集大小使用适当的 EfConstruction,考虑批量插入

召回率低

  • 原因EfSearchM 值过低
  • 解决方案:增加 EfSearch 以提高搜索时的召回率,增加 M 以提高索引质量

内存使用高

  • 原因M 值过大或未启量化
  • 解决方案:启 SQ8 量化,减少 M

🔗 相关文档