向量搜索基准测试:不同维度与数据规模下的延迟测量方法与实践)
Lance Flat暴力向量搜索基准测试不同维度与数据规模下的延迟测量方法与实践【免费下载链接】lanceOpen Lakehouse Format for Multimodal AI. Convert from Parquet in 2 lines of code for 100x faster random access, vector index, and data versioning. Compatible with Pandas, DuckDB, Polars, Pyarrow, and PyTorch with more integrations coming..项目地址: https://gitcode.com/GitHub_Trending/la/lance本文以 benchmarks/flat/README.md 为核心讲解 Lance 仓库内置的 flat无索引/暴力向量搜索基准测试如何一条命令运行完整基准、得到benchmark.csv原始数据与benchmark.html延迟曲线并结合 benchmarks/flat/benchmark.py 的完整实现与 Rust 扫描器源码说明 flat KNN 的查询路径、距离度量选择与参数设计帮助你复现并扩展这套延迟测量方案。基准测试要回答的问题Lance 的向量检索有两条路径基于 ANN 索引如 IVF_PQ、IVF_HNSW_PQ的近似检索以及不经过索引、对全量数据逐一计算距离的暴力flat检索。flat 路径的价值在于它是精确结果exact KNN的基线也是小规模数据或索引尚未就绪时的回退方案。benchmarks/flat目录正是为量化这条路径而存在的它测量在不同向量维度、不同数据集规模、不同距离度量下flat 向量搜索的单次查询延迟。运行入口见 benchmarks/flat/README.md./benchmark.pyREADME 明确说明该脚本会产生两个产物benchmark.csv原始数据记录每个「维度 × 度量 × 数据规模」组合下的平均延迟与标准差benchmark.html延迟曲线图latency plot可交互查看。这套基准回答的典型问题是在 10 条到 2 万条向量之间精确 KNN 的延迟如何随数据量线性增长128 维SIFT 类与 1536/2048 维大模型嵌入类之间的差距有多大L2、cosine、dot 三种度量的计算开销是否一致基准脚本的完整设计benchmarks/flat/benchmark.py 是一个自包含脚本仅依赖lance、numpy、pandas、pyarrow并用 Plotly 作图见 第 24-25 行 的pd.options.plotting.backend plotly设置其核心参数矩阵定义在main()中第 63-67 行def main(): # make sure we cover sift, BERT, ada2 dims [128, 512, 768, 1536, 2048] lengths [10, 100, 1000, 5000, 10000, 20000] metrics [L2, cosine, dot]参数选取有明确的实践依据参数取值含义dims128、512、768、1536、2048注释写明覆盖 SIFT128 维、BERT768 维、ada21536 维等常见嵌入维度lengths10 → 20000数据集行数从极小规模到数万级用于观察延迟随数据量的增长曲线metricsL2、cosine、dot三种距离/相似度度量检验度量类型对 flat 搜索开销的影响数据生成与写入对每一组(dim, length)组合脚本生成随机向量并写入 Lance 数据集第 71-81 行data np.random.random((length, dim)).reshape(-1).astype(f) # float32 arr pa.FixedSizeListArray.from_arrays(data, list_sizedim) t pa.Table.from_arrays([arr], names[vector]) ds lance.write_dataset( t, test.lance, modeoverwrite, )注意两个实现细节向量以FixedSizeListfloat32类型存储列名为vector这是 Lance 向量检索的列约定每次都用modeoverwrite重写同一个test.lance即每个组合都测量一个干净的单文件数据集避免历史版本干扰。延迟测量方法预热 多轮取统计量单个查询的测量逻辑在benchmark()第 28-60 行遵循了基准测试的标准做法——先预热、再多轮计时def benchmark(ds: lance.LanceDataset, dim: int, metric: str): queries [np.random.random((dim,)).reshape(-1) for _ in range(32)] # warmup for query in queries: ds.to_table( nearest{column: vector, k: 10, q: query, use_index: False} ) latency [] for _ in range(10): for query in queries: start time.perf_counter() ds.to_table( nearest{ column: vector, k: 10, q: query, use_index: False, metric: metric, } ) latency.append(time.perf_counter() - start) latency np.array(latency) mean latency.mean() * 1000 std latency.std() * 1000 print(fLatency: {mean} ms, std: {std} ms) return mean, std测量口径可以拆成三点use_indexFalse是这套基准的关键开关。无论数据集上是否存在向量索引该参数强制走暴力检索路径保证测量对象始终是 flat KNN 而非 ANN 索引Python 端nearest参数的文档也说明了这一点——在 python/python/lance/dataset.py 中to_table的nearest文档提到可以「even if present by specifyinguse_indexFalse」来跳过索引32 个随机查询 × 10 轮共 320 次计时样本最终报告平均值与标准差毫秒标准差用于判断系统抖动预热循环在正式计时前对同一批查询各执行一次让文件读取、缓冲区等一次性开销提前发生。查询参数固定为k10、查询向量与数据同为 float32 随机数度量则按外层循环切换为 L2 / cosine / dot。输出CSV 原始数据与 HTML 延迟曲线脚本把每一组结果追加进latency_data第 82-93 行latency_data.append( { # this is an unfortunate hack to make the plot work # plotly cant handle multiindex dim_metric: f{dim}_{metric}, length: length, latency: latency, std: std, } )随后第 95-102 行df pd.DataFrame(latency_data) df.to_csv(benchmark.csv, indexFalse) fig df.pivot(indexlength, columnsdim_metric, valueslatency).plot( titleFlat Vector Search Latency vs. length of dataset, labels{value: latency (ms)}, ) fig.write_html(benchmark.html)benchmark.csv的列结构为dim_metric, length, latency, std其中dim_metric是「维度_度量」拼接串如128_L2。源码注释解释了这个「hack」Plotly 不支持 multiindex所以把维度与度量压进一列pivot 后每个dim_metric成为一条曲线benchmark.html以数据集行数length为横轴、平均延迟ms为纵轴每条曲线对应一个「维度×度量」组合可直接在浏览器打开交互查看。源码视角use_indexFalse走的是哪条执行路径结合 Rust 侧实现可以看到 flat 检索的落地位置。当查询要求不使用索引时DataFusion 扫描计划在 rust/lance/src/dataset/scanner.rs 中直接调用scanner.flat_knn(plan, vector_query)为计划追加暴力 KNN 节点。flat_knnrust/lance/src/dataset/scanner.rs#L6624做了两件事fn flat_knn(self, input: Arcdyn ExecutionPlan, q: Query) - ResultArcdyn ExecutionPlan { // Resolve metric_type if not set (use default for the columns element type) let metric_type match q.metric_type { Some(m) m, None { let (_, element_type) get_vector_type(self.dataset.schema(), q.column)?; default_distance_type_for(element_type) } }; ... let flat_dist Arc::new(KNNVectorDistanceExec::try_new_batch( input, q.column, q.key.clone(), KnnBatchParams { is_batch: ..., query_count: ..., k: q.k, lower_bound: q.lower_bound, upper_bound: q.upper_bound, distance_type: metric_type, retain_vector }, )?);由此可以印证基准脚本的几个设计选择度量解析若查询未显式给出metric会按向量列的元素类型推断默认度量基准脚本显式传入metric正是为了把 L2、cosine、dot 三者作为受控变量逐一测量flat KNN 是一个独立的物理算子KNNVectorDistanceExec它扫描输入计划产出的全部行并计算距离因此延迟近似与length数据量成正比、与dim每行计算成本成正比——这正是benchmark.html曲线要验证的形状该路径不依赖任何预建索引文件与 docs/src/quickstart/vector-search.md 中「Search Without an Index」章节描述的行为一致未建索引时同样全表计算距离文档也指出「Without the index, the search will scan throughout the whole dataset to compute the distance between each data point」。另外rust/lance/src/dataset/scanner.rs#L1089 附近注释提到即使存在 ANN 索引未被索引覆盖的 fragment 仍会走 flat 分支补漏——也就是说 flat KNN 不仅是一个「基准模式」也是混合索引场景下的兜底执行路径这解释了为什么 Lance 将其作为一个独立、可强制启用的查询选项长期维护。如何解读结果与复现注意事项复现与解读这套基准时有几条适用前提值得注意均可从脚本代码确认数据是均匀随机向量不是真实嵌入。np.random.random生成的数据分布与 SIFT、BERT 等真实数据集不同随机数据下 cosine/dot 的区分度很低因此测得延迟可以反映「计算与扫描开销」的量级对比但不应外推为真实召回或延迟表现本地磁盘直读。脚本将数据写入当前目录下的test.lance测量包含文件 I/O。参考 docs/src/quickstart/vector-search.md 的性能说明存储介质本地盘 / 对象存储 / 网络盘会直接影响实测数值规模上限 20000 行。flat 检索延迟与数据量线性相关脚本刻意把长度控制在数万以内使其能在一台普通机器上跑完 5×6×3 90 个组合若要测量更大规模需要自行调整lengths输出物是相对路径。benchmark.csv与benchmark.html写在脚本运行目录下test.lance数据集也会残留在当前目录复现时注意清理或改写到临时目录可复制脚本后修改仓库本身是只读的。小结benchmarks/flat提供了一个轻量、可复现的 flat 向量搜索延迟基准一条./benchmark.py命令遍历 5 种维度、6 种数据规模、3 种度量用「预热 32 查询 × 10 轮」的口径测量use_indexFalse下的精确 KNN 延迟最终产出benchmark.csv原始数据与benchmark.html交互曲线。其测量口径与 Lance 扫描器中flat_knn→KNNVectorDistanceExec的执行路径一一对应既可作为评估 flat 检索性能基线的工具也适合作为在 ANN 索引与暴力检索之间做取舍时的对照实验模板。【免费下载链接】lanceOpen Lakehouse Format for Multimodal AI. Convert from Parquet in 2 lines of code for 100x faster random access, vector index, and data versioning. Compatible with Pandas, DuckDB, Polars, Pyarrow, and PyTorch with more integrations coming..项目地址: https://gitcode.com/GitHub_Trending/la/lance创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考