Skip to content

Querying

原文链接:https://www.yuque.com/yangguangfanxing/nmhuv1/rwgt2m3mdq4xzww1

Recap

现代应用需要向量数据库 = 向量存储 + 语义搜索

插入向量:

  1. 创建嵌入向量
  2. 存入专用数据库(附带属性)

查询数据: 3. 将查询嵌入为向量 4. 找到 的最近邻

RDBMS 与 VDBMS 对比

不同需求 → 不同设计

维度传统数据库 (RDBMS)向量数据库 (VDBMS)
数据记录 (Records)向量 (Vectors)
查询关系代数最近邻 + 过滤
高级查询JOIN, GROUP, FK, 游标
更新部分记录、多条记录整体向量、插入/删除/替换
一致性强一致 + 事务最终一致,可调
索引更新
存储行/列存储, LSM向量是不透明 blob
硬件/成本均匀、适中多样、昂贵(GPU)
架构更单体化更分离化

关键挑战: 大向量、无结构、更新慢

Querying

问题定义

  • 已知:查询向量
  • 目标:找到"某些"在 附近的向量

三个核心问题

  1. 什么是"附近"? → 相似度分数
  2. 哪些向量? → 各种查询类型
  3. 何时返回? → 尽可能快

距离 / 相似度评分

给定向量 ,计算表示相似性/距离的数值。

名称函数 值域
欧氏距离 (Euclidean)
内积 (Inner Product) / MIPS
余弦相似度 (Cosine)
马氏距离 (Mahalanobis)
汉明距离 (Hamming) 的个数
曼哈顿距离 (Manhattan)

注: 内积和余弦是相似度(值越大越近),需反转才能用作距离。

MIPS = Maximum Inner Product Search。

相似度转距离

将相似度分数 反转的方法:

  1. 简单反转: 使用

  2. 余弦距离:

  3. 内积转换(增加一维):

  1. Sigmoid 变换(数值不稳定,不常用):

kNN 查询(核心查询)

找到 个最近邻。

形式化定义:

返回 满足:

pgvector 示例:

SELECT * FROM items
ORDER BY vec <-> '[1,6.4,-2.1]'
LIMIT 5;

范围查询(Range Query)

返回指定半径 内的所有向量:

pgvector 示例:

SELECT * FROM items
WHERE vec <-> '[1,6.4,-2.1]' < 4;

不常用,因为应用中难以确定合适的

谓词查询(Predicated Queries)

别名: 属性过滤、混合查询(Hybrid Queries)

定义: kNN/范围查询 + 对关联属性的谓词过滤。

Pinecone 示例:

index.query(
    namespace="products",
    vector=[0.81, 0.46, 0.41, 0.64, 0.11],
    filter={
        "price": {"$lt": 100},
        "color": {"$eq": "green"}
    },
    top_k=3,
    include_metadata=True
)

核心问题

ANN (Approximate Nearest Neighbors) 索引与属性索引不兼容!

  • 预过滤(Prefiltering): 先按属性过滤 → 再 kNN

  • 后过滤(Postfiltering): 先 kNN → 再按属性过滤

三种过滤策略

  1. 预过滤 + 全表扫描

  2. 后过滤 + 增大

  3. 单阶段扫描(Holy Grail)

示例实现

方法说明产品
Block-first (预过滤)构建谓词位图,kNN 时使用Milvus, AnalyticsDB-V
Pre-partition (预过滤)按属性范围预分区,查询多个分区合并Milvus
Visit-first (单阶段)从最近邻开始,逐步添加满足过滤条件的下一邻居Timescale (pgvectorscale / StreamingDiskANN)

多向量查询(Multi-Vector Queries)

别名: 混合搜索、多模态搜索

场景:

  • 同时在多个向量空间搜索
  • 单个实体有多个向量(如文本 + 图像、多角度人脸、多尺度编码)
  • 使用多个嵌入模型

朴素方法

  1. 执行 次 kNN 搜索 → 得到 个向量
  2. 合并分数(最小值、加权平均、最大值、学习组合等)
  3. 选择 top

问题: 分数合并方式可能导致漏掉真正的最近邻。

经典 top-k 算法的问题

需要"获取下一候选"操作 → 大多数向量索引不支持!

高级方法

  1. 向量融合(Vector Fusion)

  2. 迭代合并(Milvus)

  3. MUST [Wang, ICDE'24] — 最新研究成果

  4. Timescale 流式检索索引 — 最新研究成果

重排序(Reranking)

许多 VDBMS 提供查询后的重排序步骤。

流程:

  1. 获取 kNN 结果集
  2. 应用重排序模型重新排序

原因:

  • 距离分数衡量的是相似性,而非相关性
  • 近似索引引入误差
  • 重排序可以使用更复杂的模型
  • 可以引入上下文信息

效果示意:

排序前:a  b  c  d  e  f  g  h  i  j
                               ↓ 重排序模型
排序后:c  j  b  g  i  d  a  h  e  f

精确 kNN 很慢!

暴力搜索:

  • 对所有 计算 ,再排序/用优先队列
  • 时间复杂度: top-k 时间
  • 支持精确 kNN、范围查询、谓词查询等所有类型

解决方案:近似最近邻搜索(ANNS)

ANNS 索引的权衡

好处代价
搜索更快准确度降低
-更多内存
-更慢的更新

示例:基于聚类的索引

  • 构建: 聚类向量,关联到最近质心
  • 查询: 找到离 最近的质心,搜索其列表
  • 误差: 在边缘时可能漏掉更近的邻居

用心记录,持续成长