前言
ES的官方实验室曾发布过一篇博客,介绍了使ES向量检索性能获得显著提升的技术要点与展望:
- 多线程搜索能力的利用:Lucene 的分段架构允许实现多线程搜索能力。Elasticsearch 通过同时搜索多个段来提高性能,使用所有可用的 CPU 核心的计算能力显著减少了单个搜索的延迟。
- 加速多图向量搜索:通过在邻近图中平衡探索和利用,调整扩展匹配集的大小,控制运行时间和召回率之间的权衡,这对于在多个图中实现最佳搜索性能至关重要。
- 信息交换优化:在多图搜索场景中,通过智能地在搜索之间共享状态,使基于全局和局部竞争阈值的遍历决策更加明智,从而提高搜索效率。
- Java 最新进展的利用:通过 Project Panama Vector API,Java 代码现在可以无缝地与 SIMD 指令交互,解锁矢量引擎。
- 标量量化:Lucene 引入了标量量化技术,这是一种有损压缩技术,可以在不牺牲搜索性能的情况下显著减少内存需求。
- 压缩技术的改进:通过将每个维度从 7 位压缩到 4 位,进一步减少了数据大小,同时保持了搜索结果的准确性。
- 二进制量化的探索:未来可能会将二进制量化技术集成到 Lucene 中,这有可能彻底改变向量存储和检索。
- 多向量集成:Lucene 和 Elasticsearch 通过嵌套字段和连接功能,支持在顶级文档中管理多个嵌套文档,允许跨嵌套文档进行搜索,并随后与它们的父文档连接。
- 预连接优化:在搜索子向量段落时,Lucene 能够在搜索 HNSW 图的同时预先连接到父文档,确保返回的是文档而不是段落,这提高了效率。
这些技术如果得到集成,大部分是对用户透明的,我们今天要说的是在实践层面,对于向量检索有哪些调优考虑。
段合并只有20%的性能提升吗?
在之前的初步测试中,我们已经得出一个确定的结论(ESrally
已专门为此设计了测试用例),在测试工具默认参数的情况下,段合并可以带来全面的 20%性能提升(也就是无论其他参数如何变换,QPS
和latency
性能表现提升趋势接近一致)。
我们观察数据量(约 260 万 96 维数据):
原始文档的大小解压缩后是 20 GB。
将数据写入ES后索引实际占用的存储:
# 合并前:4.5GB
curl http://localhost:9200/_cat/indices/vectors?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
green open vectors f4iuM6vjTGiBwz8lofwqFw 2 0 2500000 0 4.5gb 4.5gb 4.5gb## Running force-merge 100%- 合并后:1GB
curl http://localhost:9200/_cat/indices/vectors?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
green open vectors f4iuM6vjTGiBwz8lofwqFw 2 0 2500000 0 1gb 1gb 1gb
跟随后续的并发调优,我们可以看出段合并的巨大优势,不止 20%!
并发 QPS 调优
并发10的情况
无法直接修改搜索并发,需要改动源码目录 .rally/benchmarks/tracks/default/dense_vector/challenges
的 default.json
:
# 修改示例
{"name": "knn-search-100-1000_multiple_segments","operation": "knn-search-100-1000","warmup-iterations": 100,"clients": 10,"iterations": 1000
}
测试指令:
./esrally race --track-path=/root/.rally/benchmarks/tracks/default/dense_vector --target-hosts=localhost:9200 --pipeline=benchmark-only --offline --report-file=/home/elastic/ssd_dv_s2-c1-30g-d1-sc10-1.csv --report-format=csv --track-params="bulk_indexing_clients:1" --user-tags="shards:2,clients:1,mem:30g,disk:1,sc:10"
对比基线为全默认值,变量为 sc:10
,也就是搜索并发度为 10。
比较两次测试结果:
./esrally compare --baseline b337fb0a-39cf-4119-abe5-6dd4be745a32 --contender 576b29d8-98a0-458d-8af1-27830068df80 --report-file /home/elastic/dv-shards2-sc10_1.csv --report-format csv
-
knn-search-10-100 +883.02%
-
knn-search-100-1000 +866.39%
-
knn-search-10-100_multiple_segments +496.02%
-
Knn-search-100-1000_multiple_segments +269.07%
在 10 搜索并发的情况下,对比结果显示 QPS 相比默认参数提高数倍。而且,段合并对性能的影响也放大了。
CPU 使用率明显上升了:
总体 52.9%使用率, es 进程使用了 2538% 的 CPU。
注意,每轮测试需主动删除 ES 中的测试索引(vectors
)!
curl -XDELETE http://localhost:9200/vectors
继续测试
并发 20/30/40/50 的情况。
20 search
Mean Throughput,knn-search-10-100_multiple_segments,169.83212959330336,1223.2297240422738,+1053.39759,ops/s,+620.26%90th percentile latency,knn-search-10-100_multiple_segments,4.8985810310114175,15.743541764095427,+10.84496,ms,+221.39%99th percentile latency,knn-search-10-100_multiple_segments,6.255753734731111,61.14699723257214,+54.89124,ms,+877.45%Mean Throughput,knn-search-100-1000_multiple_segments,71.8843832772858,286.788544718593,+214.90416,ops/s,+298.96%99th percentile latency,knn-search-100-1000_multiple_segments,15.602529068710282,114.20343654463056,+98.60091,ms,+631.95%Mean Throughput,knn-search-10-100,198.15221100022976,4285.480938609085,+4087.32873,ops/s,+2062.72%99th percentile latency,knn-search-10-100,3.9556266699219123,3.956923596560939,+0.00130,ms,+0.03%Mean Throughput,knn-search-100-1000,93.08795806647417,2109.4832627430874,+2016.39530,ops/s,+2166.12%99th percentile latency,knn-search-100-1000,13.300802457379177,12.577712316997342,-0.72309,ms,-5.44%
30 search
后续仅记录代表性的结果:
Mean Throughput,knn-search-10-100,198.15221100022976,5736.259111262101,+5538.10690,ops/s,+2794.88%Mean Throughput,knn-search-10-100_multiple_segments,169.83212959330336,1253.008883159874,+1083.17675,ops/s,+637.79%
注意到,多段的检索性能已经达到瓶颈了,1223 -> 1253 ops。
40 search
# 合并段
Mean Throughput,knn-search-10-100,198.15221100022976,6327.666524710088,+6129.51431,ops/s,+3093.34%# 多段
Mean Throughput,knn-search-10-100_multiple_segments,169.83212959330336,1307.2178700891045,+1137.38574,ops/s,+669.71%## 延迟
99th percentile latency,knn-search-10-100,3.9556266699219123,8.661079301964493,+4.70545,ms,+118.96%99th percentile latency,knn-search-10-100_multiple_segments,6.255753734731111,112.7571176411585,+106.50136,ms,+1702.45%
监控数据显