想象你经营着一座巨型图书大厦。每本书入库时,都会遇到一位“语义图书管理员”——它快速读完全书,在卡片上写下一串数字,这些数字合起来就是这本书的“意义坐标”。讲数据库的书和讲存储的书,坐标会挨得很近;菜谱则远远待在美食区。过去,数据库只能按书名精确匹配;如今,pgvector 这个 PostgreSQL 扩展把“意义坐标卡”变成了数据库的一等公民:存向量、量距离、建索引,一条 SQL 就能把“意思最像的十本书”捞出来。从嵌入向量到相似度检索,再到 RAG 应用的完整链路,都建立在这套机制之上。本篇文章就以这座图书大厦为线索,一步步拆解 pgvector 的安装、度量、索引与调优。

岗位关联

掌握 pgvector,等于给关系型数据库装上“语义搜索”引擎——这是搭建 RAG、向量检索应用的必备技能,也是 AI 工程师吃透数据底座的关键一步。

目录
  1. 可视化演示
  2. 向量嵌入基础
  3. 距离度量选择
  4. ivfflat索引
  5. hnsw索引
  6. 调优实践建议
  7. RAG检索应用
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

向量嵌入基础

想象你经营着一座巨型图书大厦。每本书入库时,都会遇到一位“语义图书管理员”——它快速读完全文,在卡片上写下一串数字:这批数字合起来,就是这本书的“意义坐标”。讲数据库的书和讲存储的书,坐标会挨得很近;菜谱则远远待在美食区。

这张“意义坐标卡”就是向量(embedding)。管理员读得越细致,数字越多,维度 d 就越高。pgvector 把这套能力搬进 PostgreSQL:先执行 CREATE EXTENSION vector 启用扩展,建表时用 vector(768) 声明列维度,插入时把模型输出的数组直接存进去,再借助专用运算符完成相似度排序。

语义空间映射是这一切的地基:模型把“苹果”和“水果”映射到相邻坐标,哪怕两个词没有一个字相同——这是传统 LIKE '%苹果%' 永远做不到的。维度必须和嵌入模型输出严格对齐,否则距离计算与索引全部失效,就像楼层索引和实际书架对不上号。

有了坐标卡,大厦从“按书名找书”升级为“按意思找书”。但坐标卡只是一堆数字,怎么判断“意思相近”?——下一节,我们来挑尺子。

fθ(book)=v⃗∈Rd\displaystyle f_{\theta}(\text{book}) = \vec{v} \in \mathbb{R}^{d}
公式含义:语义编码模型 $f_{\theta}$ 把一本书映射为 d 维实数向量,向量就是书在语义空间里的坐标卡。
  1. 编码器映射“语义图书管理员”的判断逻辑就是 $f_{\theta}$,它把输入对象变成输出向量。
    fθf_{\theta}
  2. 输入对象$\text{book}$ 指任意文本或图片,即大厦里等待入库的一本书。
    book\text{book}
  3. 输出坐标$\vec{v}$ 是 d 维实数数组,即书的意义坐标卡。
    v⃗∈Rd\vec{v} \in \mathbb{R}^{d}
  4. 空间含义$\mathbb{R}^{d}$ 表示 d 维语义空间,是所有坐标卡能够落脚的“意义地图”。
    Rd\mathbb{R}^{d}

距离度量选择

大厦里备着好几把尺子。第一把叫“余弦尺”,它只看方向:两本书的坐标卡无论长短,只要夹角小就算“意思相近”。这很妙——一篇长报告和一条短摘要向量长度差好几倍,但语义方向一致,余弦尺照样判为同道。

第二把叫“L2 尺”(欧式距离),它直接拉一根直线量两本坐标卡之间的绝对距离,差一点就是差一点。当“幅度”本身携带信息时——比如图片特征、用户行为嵌入——L2 更可靠。pgvector 里 <=> 是余弦距离,<-> 是 L2,<#> 是内积。

余弦距离的算式由“点积 ÷ 双模长”得到相似度,再取 1 补成距离;L2 则把每个维度的差平方求和再开方。选尺子决定了建索引后的距离算法,也提醒你:用余弦时要考虑是否先对向量做归一化。

归一化的妙处在于:把向量都拉成长度 1 后,余弦距离与 L2 距离的排序结果等价——管理员从此一条路走到黑,两把尺子通用。距离度量的本质是“你到底在乎方向还是位置”,这一步想清楚,后面的索引调优才有意义。

cos_dist(a⃗,b⃗)=1−a⃗⋅b⃗∥a⃗∥ ∥b⃗∥\displaystyle \text{cos\_dist}(\vec{a}, \vec{b}) = 1 - \frac{\vec{a} \cdot \vec{b}}{\lVert \vec{a} \rVert \, \lVert \vec{b} \rVert}
公式含义:逐维度求差、平方、累加、开方,得到两点间的欧式直线距离。
  1. 维度差分$a_i - b_i$ 表示两个坐标卡在第 i 位上的数值差距。
    ai−bia_i - b_i
  2. 平方放大$(\cdots)^2$ 消除正负号,同时放大较大差距的权重。
    (ai−bi)2(a_i - b_i)^2
  3. 累加全部维度$\sum_{i=1}^{d}$ 把 d 个维度上的差距全部加起来。
    ∑i=1d(ai−bi)2\sum_{i=1}^{d} (a_i - b_i)^2
  4. 开方还原$\sqrt{\cdots}$ 把平方和还原成直观的直线距离。
    ∑i=1d(ai−bi)2\sqrt{\sum_{i=1}^{d} (a_i - b_i)^2}

ivfflat索引

书越来越多,逐本量距离不现实。ivfflat 的招数是“先分楼层”:建索引时用 K-means(一种自动聚堆的聚类算法)把全库向量分成 lists 个簇,每簇选一个中心坐标,相当于在大厦里划出几十个主题楼层。

查询时,导航员先算查询向量离哪个簇中心最近,只进那个桶做全量精确比较——这就是名字里的 flat(桶内扁平扫描)。但书可能恰好躺在两个楼层交界处,只查一个桶会漏,于是引入 probes:查询时额外多探测几个相邻桶。

lists 是建索引时的参数,决定桶的粗细程度;probes 是查询时的参数,决定顺路看几个桶。两者配合:lists 太少则桶大扫描慢,lists 太多则边界误差大;probes 越大候选越全,代价是延迟升高。ivfflat 适合“海量数据 + 容忍少量漏检”的场景。

一句话记住 ivfflat:先找对楼层,再在楼层里精挑细选。它构建快、内存小,但召回率受参数影响明显,数据分布大变后最好重建索引——楼层布局过时了,导航自然不准。

c⃗∗=arg⁡min⁡c⃗j∈C∥q⃗−c⃗j∥2\displaystyle \vec{c}_{*} = \arg\min_{\vec{c}_j \in C} \lVert \vec{q} - \vec{c}_j \rVert_2
公式含义:查询时把向量 q 分配给离它最近的簇中心,只在该簇内做精确搜索。
  1. 簇中心集合$C$ 是建索引时划分出的全部桶中心坐标。
    CC
  2. 查询向量$\vec{q}$ 是你正在找的那本书的坐标卡。
    q⃗\vec{q}
  3. 距离计算$\lVert \vec{q} - \vec{c}_j \rVert_2$ 表示查询点与某个桶中心的 L2 距离。
    ∥q⃗−c⃗j∥2\lVert \vec{q} - \vec{c}_j \rVert_2
  4. 取最小$\arg\min$ 找出距离最小的桶中心 $\vec{c}_{*}$,查询只进入这个桶。
    c⃗∗=arg⁡min⁡c⃗j∈C∥q⃗−c⃗j∥2\vec{c}_{*} = \arg\min_{\vec{c}_j \in C} \lVert \vec{q} - \vec{c}_j \rVert_2

hnsw索引

hnsw 换了个思路,不再分楼层,而是给每本书发一张“朋友圈通讯录”,记下离自己最近的 m 个邻居。整座大厦于是变成一张多层社交网络——上层朋友少、关系远,适合快速定位大方向;下层朋友多、关系密,适合精确落地。

检索时从入口出发走贪心路线:每次从当前节点的朋友里挑一个离目标最近的,像派对上顺着人脉找目标,一步步靠近。这正是 hnsw 的检索核心——用图上的局部跳转代替全库扫描,每一步都确保“离目标更近一点”。

m 控制每个节点最多记多少个朋友,m 越大图越密、检索越准但内存越大;ef_construction 是建图时的“候选队列宽度”,越大建图越慢但图更优质。和 ivfflat 相比,hnsw 没有桶边界问题,召回更高,但图结构维护贵,高频增删的数据集会头疼。

图书大厦的交友哲学:与其满楼跑,不如托朋友的朋友打听。hnsw 用空间换精度,是“精装修”型索引,适合数据相对静态、对召回和延迟都苛刻的核心链路。

u∗=arg⁡min⁡u∈N(v)d(q⃗,u⃗)\displaystyle u^{*} = \arg\min_{u \in \mathcal{N}(v)} d(\vec{q}, \vec{u})
公式含义:在 hnsw 检索中,从当前节点 v 的朋友列表里选离查询向量最近的邻居,作为下一步。
  1. 邻居集合$\mathcal{N}(v)$ 是当前节点 v 的朋友列表,即图中与 v 相连的节点。
    N(v)\mathcal{N}(v)
  2. 候选节点$\vec{u}$ 是朋友列表中的某个邻居向量。
    u⃗\vec{u}
  3. 距离函数$d(\vec{q}, \vec{u})$ 计算查询向量与该邻居在语义空间中的距离。
    d(q⃗,u⃗)d(\vec{q}, \vec{u})
  4. 贪心选择$\arg\min$ 挑出距离最小的邻居 $u^{*}$,不断重复直到无法更近为止。
    u∗=arg⁡min⁡u∈N(v)d(q⃗,u⃗)u^{*} = \arg\min_{u \in \mathcal{N}(v)} d(\vec{q}, \vec{u})

调优实践建议

楼层和朋友圈都有了,剩下的问题是旋钮怎么拧。向量维度、ef_search、硬件预算,三件事共同决定检索的最终体验。调优的本质,是在“准”和“快”之间找到平衡点。

维度是嵌入模型的“分辨率”,由模型输出决定——比如常见的 768 或 1024 维,不是想设多大就多大。维度翻倍,存储与计算同步翻倍,而精度收益迅速递减;维度太高还会触发“维度灾难”:高维空间里所有点的距离趋于相同,检索形同抓阄。

ef_search 是 hnsw 查询时每层保留的候选队列长度,越大召回越高、延迟越高。经验做法是从 40 起步,用 Recall@k 指标边测边调,找到精度/延迟曲线的拐点。下面的公式就是衡量“索引到底多准”的统一标尺。

资源账也要算:一千万条 768 维 float4 向量裸存约 30.7 GB,再算上索引开销可能翻倍。省钱策略:能降维就降维、能用 float4 不用 float8、只对必要列建索引。电梯再快也架不住书多——先度量,再调优。

Recall@k=∣TopKapprox∩TopKexact∣k\displaystyle \text{Recall@}k = \frac{| \text{TopK}_{\text{approx}} \cap \text{TopK}_{\text{exact}} |}{k}
公式含义:用近似索引返回的 Top-k 与精确全扫描的 Top-k 做交集,交集占比即召回率。
  1. 精确结果集$\text{TopK}_{\text{exact}}$ 是对全库线性扫描得到的真正最近 k 本书。
    TopKexact\text{TopK}_{\text{exact}}
  2. 近似结果集$\text{TopK}_{\text{approx}}$ 是索引(ivfflat/hnsw)返回的 k 个候选。
    TopKapprox\text{TopK}_{\text{approx}}
  3. 取交集$\cap$ 计算两组结果中相同的书有多少本。
    TopKapprox∩TopKexact\text{TopK}_{\text{approx}} \cap \text{TopK}_{\text{exact}}
  4. 归一化除以 k 得到 0 到 1 之间的比例,越接近 1 说明索引质量越高。
    ∣TopKapprox∩TopKexact∣k\frac{| \text{TopK}_{\text{approx}} \cap \text{TopK}_{\text{exact}} |}{k}

RAG检索应用

最后回到实战:大模型回答前想“翻书”。RAG(检索增强生成)让模型先查资料再作答,pgvector 就是这座可被 SQL 直接调用的图书大厦——它把“记忆模块”搬进了关系型数据库。

落地链路很清晰:文档切块 → 嵌入模型生成向量 → 写入 pgvector → 用户提问同样嵌入 → 用 <=> 取 Top-k → 拼进 prompt 交给大模型。相比单独引入向量数据库,pgvector 让 PostgreSQL 兼任向量库,事务、备份、权限体系全部复用。

纯向量检索有一个盲区:专有名词如 “GRANT” 在语义空间很孤立,向量难命中,但关键词一搜一个准。因此生产环境常用混合检索:BM25 关键词得分 + 向量相似度加权融合,两路结果按权重 λ 合并排序,互补长短。

成本优化同样重要:块大小与重叠设计决定检索粒度;高频查询加缓存;大批量写入时先灌数据再统一建索引;嵌入模型选轻量版本。大厦的启示:检索快不是终点,让模型少编造、答得准,才是 RAG 存在的意义。

score(d)=BM25(q,d)+λ⋅sim(q⃗,v⃗d)\displaystyle \text{score}(d) = \text{BM25}(q, d) + \lambda \cdot \text{sim}(\vec{q}, \vec{v}_d)
公式含义:文档 d 的最终得分 = 关键词精确匹配得分 + 向量语义相似度得分,按权重 λ 融合。
  1. 关键词得分$\text{BM25}(q, d)$ 是传统全文检索对文档 d 的精确匹配评分。
    BM25(q,d)\text{BM25}(q, d)
  2. 语义得分$\text{sim}(\vec{q}, \vec{v}_d)$ 是查询向量与文档向量的相似度,比如余弦相似度。
    sim(q⃗,v⃗d)\text{sim}(\vec{q}, \vec{v}_d)
  3. 融合权重$\lambda$ 是人为调节的系数,控制语义分在总分中的占比。
    λ⋅sim(q⃗,v⃗d)\lambda \cdot \text{sim}(\vec{q}, \vec{v}_d)
  4. 合并排序两部分相加得到综合分,按分数取 Top-k 喂给大模型。
    BM25(q,d)+λ⋅sim(q⃗,v⃗d)\text{BM25}(q, d) + \lambda \cdot \text{sim}(\vec{q}, \vec{v}_d)

AI 应用场景

RAG 企业知识库问答

阶段:检索增强生成(推理阶段的数据检索)

解决的问题:传统关键词检索漏掉同义表达,而单独引入向量库又太重。用 pgvector 把企业文档切片嵌入,问答时可先语义检索再交给大模型生成,回答有据可依,显著降低幻觉。

具体案例:某 SaaS 公司把 5000 份产品文档切成 2 万块,用 768 维嵌入存入 PostgreSQL;客服提问“如何配置域名解析”经嵌入后命中相关章节,LLM 据此生成带操作步骤的回答,首轮解决率从 61% 提升到 84%。

电商商品语义搜索

阶段:召回与排序

解决的问题:用户说“耐脏的黑色通勤包”,传统关键词只能匹配“黑色 包”。向量检索能理解“通勤=上班背、耐脏=材质偏好”,配合余弦距离召回候选再精排。

具体案例:某电商把商品标题加属性拼成文本做嵌入,存入 pgvector;查询端同样嵌入后用 hnsw 索引取 Top-50 召回,叠加销量权重精排,搜索转化率提升 12%。

相似内容去重与推荐

阶段:离线批处理

解决的问题:内容平台需要找出重复或近似文章。L2 距离对绝对位置敏感,这里改用余弦距离配合 ivfflat 批量找近邻,兼顾速度与内存。

具体案例:某资讯 App 每晚对新增 10 万篇文章做向量嵌入,与存量 500 万篇用 ivfflat 两两比对识别近似重复,去重后信息流多样性明显提升。

Python 演示

python64 行
"""pgvector 检索原理迷你演示:精确线性扫描 vs ivfflat 式聚类近似检索"""import mathimport random  def embed(text):    """极简假嵌入:以文本哈希作种子,生成 8 维向量"""    random.seed(sum(map(ord, text)))    return [random.random() for _ in range(8)]  def cosine_dist(a, b):    """余弦距离 = 1 - 归一化点积,只看方向不看长度"""    dot = sum(x * y for x, y in zip(a, b))    na = math.sqrt(sum(x * x for x in a))    nb = math.sqrt(sum(y * y for y in b))    return 1.0 - dot / (na * nb)  def exact_search(corpus, query_vec, k=3):    """精确检索:线性扫描全部向量,取距离最小的 k 个"""    scored = sorted(corpus, key=lambda item: cosine_dist(item["vec"], query_vec))    return scored[:k]  def build_buckets(corpus, num_buckets=4):    """模拟 ivfflat 聚类:按序号取模粗略分桶"""    buckets = {}    for i, item in enumerate(corpus):        key = i % num_buckets        buckets.setdefault(key, []).append(item)    return buckets  def approx_search(buckets, query_vec, probes=2, k=3):    """近似检索:只探测前 probes 个桶,桶内精算"""    hits = []    for bucket_idx in range(probes):        hits.extend(buckets[bucket_idx])    scored = sorted(hits, key=lambda item: cosine_dist(item["vec"], query_vec))    return scored[:k]  def main():    words = ["苹果", "香蕉", "西瓜", "老虎", "狮子", "大象",             "Python", "Rust", "Go", "汽车", "轮船", "高铁"]    corpus = [{"text": w, "vec": embed(w)} for w in words]    query = {"text": "梨", "vec": embed("梨")}     exact = exact_search(corpus, query["vec"])    buckets = build_buckets(corpus)    approx = approx_search(buckets, query["vec"])     exact_ids = {item["text"] for item in exact}    approx_ids = {item["text"] for item in approx}    recall = len(exact_ids & approx_ids) / len(exact_ids)     print("精确 Top3:", [item["text"] for item in exact])    print("近似 Top3:", [item["text"] for item in approx])    print("召回率:", f"{recall:.0%}")  if __name__ == "__main__":    main()
目的:用 12 个词条模拟图书大厦的存量书籍,对比“全库精确扫描”和“ivfflat 式分桶近似扫描”的召回率差异,直观理解索引参数为何影响检索质量。
  1. random.seed(sum(map(ord, text)))用文本哈希当随机种子,让同一本书每次得到相同的坐标卡(向量)。
  2. dot = sum(x * y for x, y in zip(a, b))计算两个向量的点积,这是余弦距离的核心分子。
  3. return 1.0 - dot / (na * nb)点积除以两个模长得到相似度,再用 1 减去,翻转为距离。
  4. scored = sorted(corpus, key=lambda item: cosine_dist(item["vec"], query_vec))全库线性排序,得到“精确检索”的基准答案。
  5. key = i % num_buckets用序号取模模拟 ivfflat 的聚类分配,真实场景中由 K-means 完成。
  6. hits.extend(buckets[bucket_idx])只取前 probes 个桶的向量作为候选集,这就是近似检索的“偷懒”之处。
  7. recall = len(exact_ids & approx_ids) / len(exact_ids)用精确结果与近似结果的交集比例衡量召回率,对应正文的 Recall@k 公式。

常见误区

误区我建 ivfflat 索引时把 `lists` 设得很大,以为桶越多、划分越细,检索就一定又快又准。

正解lists 决定聚类桶数,桶太多会让每个桶里的书太少,查询时容易漏掉真正相近但落在隔壁桶的书,召回率反而下降;同时桶中心增多也会拖慢构建和定位。正确做法是让 lists 与数据规模匹配,再配合 probes 一起调。

为何常见:直觉上“更细的划分 = 更准”,却忽略了桶边界误差和桶内检索成本,把构建参数误当成万能旋钮。

误区我看到“余弦相似度 0.9 很高”,就直接拿它当距离用,结果排序和阈值过滤全反了。

正解在 pgvector 里,<=> 返回的是余弦距离,数值上等于 1 - 余弦相似度。排序时两者单调等价,但做“距离小于 0.3”这类阈值过滤时,必须清楚自己量的是相似度还是距离,否则结果截然相反。

为何常见:很多资料把 similarity 和 distance 混着写,初学者只记住“越大越相近”,忽略了“距离越大越远”的取补关系。

误区网上 benchmark 都说 HNSW 召回率高,那我所有场景直接无脑建 HNSW 索引就行。

正解HNSW 构建慢、内存占用大,数据频繁增删时图结构维护成本高;IVFFlat 内存小、构建快,适合海量数据且可容忍少量漏检的场景。选型要看数据规模、更新频率、内存预算和召回要求,没有绝对最优。

为何常见:只看了召回率数字,忽略了存储成本和更新场景,把“某个指标更好”等同于“所有维度都更好”。

误区嵌入维度设得越大,语义信息越丰富,检索一定越准,那我直接上 4096 维。

正解维度由嵌入模型决定,不能随意改,且建索引时的维度必须与模型输出严格一致。维度升高会带来“维度灾难”:距离趋于均匀、索引变大、计算变慢,精度收益却急速递减。常用做法是用降维投影(如 PCA)在精度和成本之间取平衡。

为何常见:把“信息多”等同于“效果好”,忽略了高维空间中距离度量逐渐失效的数学事实。

面试题

Q1. pgvector 中创建 vector 列时,通常还需要指定什么参数?

单选题 · easy

  • A.向量的具体维度数← 正确答案
  • B.向量索引的类型
  • C.相似度度量方式
  • D.存储引擎的名称

答案:A。vector(768) 必须显式给出维度,因为后续距离计算、索引构建都依赖维度;索引类型在 CREATE INDEX 里指定,度量方式由运算符决定,均不属于列定义参数。

Q2. 下列哪种距离度量适合“对向量长度不敏感”的语义方向比较?

单选题 · easy

  • A.欧式 L2 距离
  • B.余弦距离← 正确答案
  • C.曼哈顿距离
  • D.切比雪夫距离

答案:B。余弦距离只看向量方向夹角,对长度不敏感,适合文本语义比较;L2 对绝对位置敏感,曼哈顿与切比雪夫多用于数值型特征空间,不适合纯语义方向比较。

Q3. ivfflat 索引中的 lists 参数,其核心作用是什么?

单选题 · mid

  • A.指定聚类中心即桶的数量← 正确答案
  • B.指定查询时探测的桶数量
  • C.指定向量空间的维度大小
  • D.指定每层图中的最大连接数

答案:A。lists 是构建 ivfflat 时 K-means 聚类的簇数量;查询时探测桶数由 probes 控制;维度由列定义决定;连接数是 HNSW 的 m 参数。

Q4. 使用 ivfflat 索引查询时,增大 probes 参数通常会带来什么影响?

单选题 · mid

  • A.召回率提升但查询变慢← 正确答案
  • B.召回率下降但查询变快
  • C.构建索引时间大幅缩短
  • D.存储空间占用显著减少

答案:A。probes 决定查询时检查几个桶,桶查得越多候选集越全,召回率越高,但耗时也线性上升;构建时间和存储空间几乎不受影响。

Q5. HNSW 索引中 m 参数的作用是什么?

单选题 · mid

  • A.控制图中每个节点的最大连接数← 正确答案
  • B.控制聚类中心的数量
  • C.控制向量的嵌入维度
  • D.控制查询时的候选队列大小

答案:A。m 是 HNSW 多层图中每个节点的最大邻居数,决定图的密度;聚类数量是 ivfflat 的 lists,嵌入维度是列定义属性,查询候选队列是 ef_search。

Q6. HNSW 索引的 ef_construction 参数主要影响什么?

单选题 · mid

  • A.构建索引时的候选搜索宽度← 正确答案
  • B.查询时的固定返回条数
  • C.向量距离的计算函数类型
  • D.数据库连接池的最大数量

答案:A。ef_construction 是建图时每一层的候选队列宽度,越大图质量越高但构建越慢;查询阶段对应的是 ef_search,两者属于不同阶段。

Q7. 一张 1000 万行、每行 768 维 float4 向量的表,仅存储向量部分约需多少 GB?

单选题 · hard

  • A.约 0.76 GB
  • B.约 7.68 GB
  • C.约 30.7 GB← 正确答案
  • D.约 768 GB

答案:C。1000 万 × 768 维 × 4 字节 ≈ 3.07×10¹⁰ 字节 ≈ 30.7 GB。A 少算了三个数量级,B 是 float2 量级,D 高估了 25 倍。算清存储账才能做好调优预算。

Q8. 关于余弦距离与 L2 距离,下列说法正确的有?

多选题 · mid

  • A.余弦距离关注向量方向差异← 正确答案
  • B.L2 距离关注绝对位置远近← 正确答案
  • C.两者数值范围完全相同
  • D.归一化后两者排序结果一致← 正确答案

答案:ABD。余弦看方向、L2 看位置,A、B 正确;余弦距离范围是 [0,2],L2 范围是 [0,∞),C 错误;L2 归一化后距离平方与余弦距离线性相关,排序一致,D 正确。

Q9. 关于 ivfflat 与 HNSW 索引的对比,正确的说法有?

多选题 · hard

  • A.HNSW 通常召回率更高← 正确答案
  • B.ivfflat 构建索引更快← 正确答案
  • C.HNSW 适合频繁增删的数据
  • D.ivfflat 召回率不受构建影响

答案:AB。HNSW 图检索通常召回更高;ivfflat 聚类构建快、内存小,A、B 正确。HNSW 图更新维护成本高,不适合高频增删,C 错;ivfflat 召回受 lists/probes 及数据分布变化影响,D 错。

Q10. 在 RAG 应用中优化向量检索,下列做法合理的有?

多选题 · extreme

  • A.将查询与文档统一嵌入到同一语义空间← 正确答案
  • B.设置过大向量维度以提升精度
  • C.结合 BM25 等关键词检索混合排序← 正确答案
  • D.直接增大 ef_search 而不关注延迟

答案:AC。查询与文档必须由同一模型嵌入到同一空间才有可比性,A 对;维度过高引发维度灾难,B 错;混合检索能弥补向量对专有名词的盲区,C 对;ef_search 增大会推高延迟,需要结合 Recall@k 曲线权衡,D 错。