向量索引基准测试:揭开数据库向量搜索性能的真实面纱

监管和法律更新 比特币
钱财 qian.cx
深入解析向量索引基准测试方法论,涵盖HNSW与IVF算法对比、召回率与吞吐量权衡、过滤搜索挑战以及评测中的常见陷阱,助您做出明智的数据库选型决策。

深入解析向量索引基准测试方法论,涵盖HNSW与IVF算法对比、召回率与吞吐量权衡、过滤搜索挑战以及评测中的常见陷阱,助您做出明智的数据库选型决策。

随着人工智能技术的爆发式增长,几乎所有主流数据库都在争相加入向量搜索功能。然而,当各家厂商纷纷发布令人眼花缭乱的性能数据时,一个核心问题却被刻意回避:这些数字究竟在什么条件下测得?它们能否被验证?这种信息不对称正是向量索引基准测试存在的根本意义。本文将深入探讨如何科学、公正地评估向量索引性能,帮助读者理解那些被精心包装的数字背后真正的技术内涵。 要理解向量索引基准测试,首先必须明确什么是向量以及向量搜索的本质。向量是来自机器学习模型的固定长度浮点数数组,通常包含数百到数千个维度。其核心特性是语义相似的内容在向量空间中距离相近。

回答问题即可获得报酬

两个最常用的距离度量是L2欧几里得距离和余弦相似度,前者测量直线距离,后者仅关注向量间的角度关系而忽略长度。选择哪种距离由生成向量的模型决定,用户在查询时无权更改,使用错误的距离函数将导致完全无意义的结果。 典型的向量查询语句形如从文档表中检索与给定向量最接近的十条记录。这里的十就是参数k。问题的核心在于精确回答此查询需要计算查询向量与表中每一行的距离并排序,这本质上是一次全表扫描加上大量算术运算。无论是B树索引还是哈希索引都无法高效处理高维空间中的近邻搜索问题,因为它们根本无法理解一千五百三十六维空间中两个点之间的接近关系。

向量索引的出现正是为了打破这一困局。它采用近似最近邻搜索策略,不再扫描所有数据,而是仅检查数千个有潜力的候选点。这种方法通常能给出正确结果,但关键的"通常"二字正是基准测试需要量化的核心。要评估近似结果的质量,必须事先知道正确答案,这就是所谓的真值集。公开的近似最近邻数据集都附带标准真值标签,没有它就根本无法对近似索引进行评分。这个被省略的数字正是大多数向量搜索宣传缺乏可信度的根源,也是当前项目启动的初衷。

BC.Game Shitcode 2026:获取独家优惠和奖励

当前主流的向量索引设计可分为两大类,它们从相反方向解决同一问题,使用哪种设计直接决定了你能调整哪些参数。 层次可导航小世界图,简称为HNSW,是一种直观的图结构。其工作原理类似于跳表:向量作为节点组织成多层图结构,顶层节点稀少且链接跨度大,底层节点密集且链接紧凑。搜索从顶层开始,沿着链接向更接近查询向量的邻居跳转,当无法再接近时下降一层继续,直至遍历完所有层数。这种结构中有两个关键参数至关重要。M参数决定每个节点保留的链接数量,索引构建时固定,提高M值能增强图的连通性和召回率,但会减慢构建速度并增大索引体积。

ef_search参数控制搜索过程中保留的候选节点数量,这是一个会话级别变量,可以针对每个查询进行调整。增大该值会让搜索访问更多节点,获得更高召回率,但搜索时间相应延长。还有一个ef_construction参数控制构建期间的候选数量,但并非所有引擎都允许设置此参数,这在追求公平比较时会产生影响。 倒排文件索引,简称为IVF,采用与HNSW截然不同的策略。它不构建图结构,而是对数据进行分区,类似于表上的列表分区。构建时将向量分组到nlist个聚类中,每个聚类有一个代表性中心向量。

查询时将查询向量与各中心比较,选择最近的nprobe个聚类进行内部搜索。IVF构建速度快、内存占用小,但在相同速度下召回率通常较差,因为真实邻居可能恰好落在未搜索的聚类边界处。本项目专注于测试采用HNSW的引擎,因为这是大多数数据库的选择。将IVF引擎放在同一图表上主要衡量的将是两种算法之间的差距,而非各引擎的实现质量。 理解向量索引性能的关键在于认识到召回率本质上是一个设置参数,而非引擎的固有属性,而ef_search就是调节它的旋钮。以同一个HNSW索引在相同硬件上的测试为例,当ef_search设置为十时,搜索过程中仅追踪十个候选节点,系统达到每秒三千六百七十八次查询,但召回率仅为零点九五九三。

当ef_search提升到八百时,搜索速度降至每秒四百零九次查询,但召回率攀升至零点九九八七。保留八百个候选节点而非十个意味着找到更好的答案,但耗时增加了九倍。这两组数据都是对同一索引在相同硬件上的诚实测量。正因如此,"我们的数据库每秒能处理三千六百七十八次向量查询"这样的表述毫无意义,你不知道它返回错误结果的频率有多高,而引用这句话的人自己可能也不知道。反之亦然,没有吞吐量支撑的召回率同样毫无价值,因为只要关闭索引进行全表扫描,召回率总能轻松达到一点零。 本项目采用的测试方法在每个引擎上部署一张统一结构的表,包含自增主键、仅用于过滤测试的整型标签列、向量列以及基于配置的M参数构建的HNSW索引。

测试包含两类查询:普通的top-k搜索以及带过滤条件的同一搜索。标签列的取值范围为零到九十九均匀分布,因此标签小于十的过滤条件大约通过百分之十的行,标签小于一则通过约百分之一的行,这正是控制选择性的方法。不同引擎的表结构创建语法差异很大,有的在CREATE TABLE语句内声明索引,有的需要单独的CREATE INDEX语句,距离函数的命名也各不相同。将这些差异统一封装是测试驱动层的职责,驱动层也是整个测试框架中唯一与具体引擎相关的代码。 每个引擎都有一些会悄无声息地破坏测试结果的配置细节。PostgreSQL就是典型例子,它会将过大的值存储在称为TOAST的独立区域中,一千五百三十六维的向量肯定算过大。

除非将列设置为STORAGE PLAIN,否则每次距离比较都要付出额外的获取代价。这只是一行数据定义语言的问题,但如果忽略它,PostgreSQL的测试结果会因完全无关的原因显得很慢,而从结果数据中根本无法察觉。 测试框架的评估维度涵盖多个层面。召回率与吞吐量的关系通过迭代ef_search参数并记录各点的召回率和每秒查询数来构建曲线,同时在几个M值下重复此过程。k始终固定为十。查询向量来自数据集自带的保留查询集,绝不能使用已加载到索引中的行作为查询,因为搜索已存在于索引中的向量是一个简单得多的问题,会让所有引擎的成绩都虚高。

这两个参数的行为差异显著影响了测试运行时间,ef_search是会话变量,迭代时复用已构建的索引,每增加一个测试点几乎不产生额外开销;M则固化在索引结构中,每个M值都需要删除表并重新加载整个数据集。在百万级一千五百三十六维向量上,每个M值都要耗费数小时,因此测试会采集大量ef_search点但仅测试少数M值。 构建成本包括挂钟时间、每秒加载行数、磁盘上索引大小和峰值内存。这是整个基准测试中最容易发布误导性数字的环节,因为不同引擎的索引构建方式截然不同。引擎可能采用增量构建或批量构建,甚至两者兼有。增量构建在每次插入时更新图结构,加载速度慢,但最后一行插入完成时索引即构建完毕,表立即可查询。

批量构建先加载所有数据,然后一次性构建整个图,总耗时大幅缩短,但表在构建完成前无法回答向量查询。这两种方式测量的是完全不同的操作。本项目在同时支持两种方式的引擎上分别测试,并在报告中明确标注。 峰值内存从数据库容器的资源使用中提取,确保容器内只有数据库运行。测试客户端运行在独立容器中,通过私有网络连接数据库服务器。这种隔离至关重要,因为客户端需要在内存中保存整个数据集,占用数GB的Python数组。

若与数据库共享容器,容器的内存统计会将客户端数组计入数据库内存,所有发布的内存数据都会被客户端持有量虚增。 并发测试在一到三十二个客户端下测量吞吐量和延迟百分位数。引擎的图缓存策略差异巨大,这种差异只有在多个客户端竞争同一缓存时才会显现。报告同时呈现原始吞吐量数据和相对于理想加速比的达成率,因为一个在两个客户端后吞吐量停滞、同时p99延迟恶化十五倍的引擎,与一个持续扩展的引擎表现完全不同,仅看吞吐量数据完全掩盖了这种差异。 过滤搜索在多个选择性条件下测试,包括低至百分之一行通过的情况。这是将向量保留在数据库中而非专用向量存储的核心理由,理应获得比目前更多的关注。

过滤改变了"正确"的定义。在标签小于十的过滤条件下真实的top十并非全表的真实top十,因此每种选择性都需要对仅通过过滤的行重新暴力计算真值集。曾有一段时间,团队将过滤搜索的得分与全表真值集对比,导致所有引擎表现糟糕,而问题完全出在测试方法本身。现在真值集按数据集、k、行数和选择性进行键控管理。 部分查询返回少于十行的结果。在某次测试中,二百个查询中有八十一个出现这种情况。

这并非数据耗尽,因为在百分之十选择性下约有九万九千行通过过滤,总有至少十行可找。原因是操作顺序,HNSW先按距离搜索再应用WHERE子句,先收集数千个候选,再由过滤条件剔除大部分,最终剩余可能不足十行。如果过滤条件确实只匹配少于十行,真值集相应缩小,引擎仍得满分。召回率定义已妥善处理此情况,引擎未返回的行计为失误,因此六个正确行得零点六。报告会展示返回行数,因为"十行其中四个错误"和"六行全部正确"都得分零点六,前者需要扩大搜索范围,后者需要采用迭代扫描。行数信息能区分这两种本质不同的问题。

测试还包含变更测试,即在删除和重新插入部分语料库前后测量召回率和吞吐量,因为删除操作会留下指向不存在行的图边。重新构建索引是否能恢复性能尚未明确测试,这是下一步显然要探索的方向。 为确保比较的公平性,所有测试运行两遍。标准化测试为所有引擎分配相同的CPU、内存和缓存预算,差异归因于实现而非资源倾斜。调优测试允许每个引擎使用其官方文档推荐的设置。调优测试更贴近实际但控制变量更少,这恰恰是它无法取代标准化测试的原因。

两种测试下结果一致的结论才真正关于引擎本身。在两种测试间翻转的结果则因完全不同的原因值得关注。 硬件配置的细节同样关键。核心被显式绑定,每个物理核心对应一个逻辑CPU,因为SMT兄弟线程共享执行单元,同一核心上的两个线程表现与两个独立核心截然不同。混合架构芯片上绝不允许性能核与能效核混用,因为核心类型间迁移引入的方差超过许多待测量效应。各引擎采用相同的耐久性设置,避免比较的是默认fsync策略而非向量搜索本身。

某些差异根本无法消除,团队将其记录在案而非装作不存在。仅一个引擎支持的参数在标准化测试中保持未启用状态,避免赋予该引擎独家调优维度。某个引擎坚持的特定隔离级别会被设置为全局默认值。明显属于占位符的默认值会从共享预算中获得合理配置,例如某个引擎家族仍默认使用十六MB的图缓存,这显然不够,以这种预期用户会修改的值评价引擎毫无意义。所有这些都体现在结果上方的"已知非对称性"章节中。 一个常被忽视的硬件注意事项是,多个实现使用手写AVX-512指令进行距离计算,单条指令可同时处理十六个浮点数的算术运算。

同一索引在不支持AVX-512的CPU上实质上是另一场基准测试,且不同引擎的减速幅度各异,无法通过简单缩放来补偿。因此CPU型号及其特性标志被记入每次运行的清单,同时记录引擎版本与提交哈希、镜像ID以及实际解析后的资源限制。无清单则无报告。 解读结果时务必先阅读有效性章节。本项目的报告按环境、有效性、已知非对称性、结果的顺序组织,这一顺序经过深思熟虑。失败的阶段、返回结果集过短的引擎、缺少所需指令集的CPU,所有这些信息都在读者形成判断之前呈现在眼前。

最需要警惕的是静默的全表扫描。这些引擎中的任何一个都可能悄悄放弃使用向量索引转而扫描全表。扫描返回精确结果但速度缓慢,在输出中表现为高召回率与低吞吐量,这与保守调优的索引难以区分,除非深入分析查询计划。原因往往平淡无奇,例如某个引擎的优化器在成本估算后将向量索引与全表扫描对比,当LIMIT超过表的约四分之一时选择扫描,目前尚未找到能改变此行为的设置。另一个引擎在查询请求的距离类型与索引构建所用类型不匹配时静默回退,既不报错也不警告,最终得到的是顺序扫描加排序,全程毫无提示。 因此每个驱动都会对每种配置运行EXPLAIN并检查索引名称是否出现在计划中。

任何采用扫描的配置都会记入有效性章节。这是意外产出令人印象深刻的向量基准数字的最简单途径,如果某项基准未提及对此进行检查,那么在相信其任何数据之前都应弄清原因。 对于召回率与吞吐量的关系,最有效的呈现方式是曲线而非单一数字。迭代ef_search,绘制召回率与吞吐量的散点图,保留最佳点集:对于每个准确度水平,选取所有引擎在该水平下达到的最高吞吐量。一个引擎仅当其曲线在相同召回率下位于另一引擎之上时才胜出。若曲线交叉,则答案确实取决于所需的准确度水平,如实陈述这本身就是有价值的结论。

曲线确实容易引导人们比较形状而非特定点的高度,因此报告同时提供柱状图,呈现召回率底线为零点九零、零点九五和零点九九时的吞吐量数据。选择实际可接受的准确度水平,横向比较即可。 在搭建这套基准测试框架的过程中,团队遭遇了多个值得记录的陷阱,这些经历既是此处其他内容值得信任的原因,也是后来者的前车之鉴。初次摄入数据时测得的结果完全失真,加载路径采用每条插入一次网络往返并开启自动提交,测得每秒八十八行。将每事务批量五百行后,同一引擎达到每秒三百七十三行。若发布首个数字,相当于在测试自己的客户端而非数据库。

过滤搜索与变更测试曾错误地与全表真值集对比,即使运行中使用了行子集,导致所有引擎表现糟糕,而问题完全在测试端。如今真值集按数据集、k、行数与选择性键控管理。两次资源测试曾共用同一结果目录,近似最近邻运行器会跳过已有结果的配置,导致调优测试静默地跳过所有标准化测试已计算的内容,调优数据几乎全是标注不同的标准化数据,这一错误令人尴尬地长时间未被察觉。就绪探针存在欺骗性,某个引擎标准的"是否接受连接"检查在应该创建的数据库实际存在之前即返回成功。探针通过但首次查询失败,团队一度坚信这是引擎问题。最新的问题出在一千五百三十六维语料库上,近似最近邻运行器在父进程中保存整个数据集,在派生工作进程中再次保存,且副本不共享。

百万嵌入向量约占用十二GB,超出为服务器单独配置的容器容量,内核杀死工作进程。运行器不检查工作进程退出码,仅记录"终止一个工作进程"后正常退出且未写入任何结果,与运行正常完成的外观完全一致。三小时的运行以静默失败告终。 基准测试框架的扩展性是设计时的核心考量,避免每次有新引擎支持向量搜索时都需重建整套设施。每个新增引擎需要提供以下组件:基于固定版本构建运行时镜像和测试镜像的Dockerfile;声明端口、凭据以及哪些服务器设置对应标准化CPU和内存预算的配置文件;召回率与吞吐量测试模块;驱动层,负责创建索引、加载数据、执行查询、执行过滤查询、测量索引大小以及前述的EXPLAIN检查。 向量搜索技术正以前所未有的速度演进,数据库引擎纷纷将人工智能能力纳入核心功能。

在这场军备竞赛中,性能数字满天飞,但真正可验证、可复现的基准测试仍然稀缺。对于需要在生产环境中部署向量搜索的工程师而言,理解基准测试的方法论与陷阱比盲目相信厂商宣传的数字重要得多。召回率与吞吐量的权衡、过滤搜索的特殊性、构建路径的差异、并发扩展的行为,这些维度共同决定了某款数据库是否能满足特定应用场景的真实需求。唯有将性能数字置于严谨的方法论框架下解读,才能在向量搜索的技术洪流中保持清醒判断。 。

Stake.com Shitcode 2026:获取独家优惠和奖励 加入我的 Kraken 游戏,使用代码 4yczp84w 即可解锁高达 250 欧元的奖励

下一步
深入探讨 io_uring 在不启用预读功能时的性能特征,通过 TPC-H 基准测试对比,分析请求合并、SQ 轮询机制、CPU 缓存命中率等关键技术细节,为数据库与高性能存储系统开发者提供实用优化建议。
2026年09月01号 14点25分59秒 io_uring 无预读机制下的性能优化:深度分析与实践指南

深入探讨 io_uring 在不启用预读功能时的性能特征,通过 TPC-H 基准测试对比,分析请求合并、SQ 轮询机制、CPU 缓存命中率等关键技术细节,为数据库与高性能存储系统开发者提供实用优化建议。

了解 Firefox 在 iOS 上的内置广告拦截功能如何使用 Apple WebKit Content Blocker 与 EasyList 过滤列表,帮助用户在 iPhone 与 iPad 上屏蔽第三方广告与追踪器,实现更清爽、更隐私的浏览体验。
2026年09月01号 14点53分06秒 Firefox iOS 版广告拦截功能正式上线:更少干扰,更多控制

了解 Firefox 在 iOS 上的内置广告拦截功能如何使用 Apple WebKit Content Blocker 与 EasyList 过滤列表,帮助用户在 iPhone 与 iPad 上屏蔽第三方广告与追踪器,实现更清爽、更隐私的浏览体验。

GrapheneOS因Pixel 11疑似移除ARM内存标记扩展硬件支持,可能彻底放弃该设备并转向摩托罗拉合作。深度解析MTE技术重要性、Pixel安全生态变化以及对隐私用户的影响。
2026年09月01号 15点06分30秒 GrapheneOS或放弃Pixel 11:硬件安全功能缺失引发开源操作系统迁移抉择

GrapheneOS因Pixel 11疑似移除ARM内存标记扩展硬件支持,可能彻底放弃该设备并转向摩托罗拉合作。深度解析MTE技术重要性、Pixel安全生态变化以及对隐私用户的影响。

深入解析纽约市60街拥堵收费区对急救医疗服务响应时间的积极影响,基于NBER最新研究,揭示交通治理如何挽救生命。
2026年09月01号 15点12分30秒 纽约市拥堵收费政策如何显著缩短急救响应时间:一项开创性研究揭示交通治理与公共健康的双赢

深入解析纽约市60街拥堵收费区对急救医疗服务响应时间的积极影响,基于NBER最新研究,揭示交通治理如何挽救生命。

深入分析2026年9月Hacker News招聘贴中的热门岗位、地区分布与求职技巧,帮助工程师、产品经理和创业者精准定位机会,实现职业跃升。
2026年09月01号 15点19分26秒 2026年9月Hacker News招聘贴全景解析:洞悉职位趋势,抢占求职先机

深入分析2026年9月Hacker News招聘贴中的热门岗位、地区分布与求职技巧,帮助工程师、产品经理和创业者精准定位机会,实现职业跃升。

深入了解Monica个人CRM的重建历程,探索开源关系管理系统的未来发展方向,以及v3版本将如何重新定义个人生活数据管理的方式。
2026年09月01号 15点20分37秒 我们正在重建Monica:从零开始打造新一代开源个人CRM系统

深入了解Monica个人CRM的重建历程,探索开源关系管理系统的未来发展方向,以及v3版本将如何重新定义个人生活数据管理的方式。

深入剖析2026年上半年开源AI模型生态格局变化,揭示中国前沿实验室在参数规模上的领先优势、Qwen成为开发者默认基座模型的核心原因、注意力与采用度之间的本质差异,以及Agent作为新型用户对整个生态的重塑作用。
2026年09月01号 15点25分53秒 2026年夏季开源模型生态深度观察:中国实验室崛起、Qwen成社区基石、Agent时代来临

深入剖析2026年上半年开源AI模型生态格局变化,揭示中国前沿实验室在参数规模上的领先优势、Qwen成为开发者默认基座模型的核心原因、注意力与采用度之间的本质差异,以及Agent作为新型用户对整个生态的重塑作用。