为什么Elasticsearch做向量检索时,不走ANN这条路就根本跑不通?
你有没有遇到过这样的场景:
用户搜“适合夏天穿的轻薄西装”,返回的却是几款加厚羊毛料子;
或者用图片搜“复古红砖墙咖啡馆”,结果全是现代玻璃幕墙——不是模型没训好,而是向量根本没搜对。
背后的问题往往不是Embedding质量差,而是:Elasticsearch在用暴力方式查向量。
这不是理论推演,是我在三个不同行业客户现场踩出来的坑——电商中台把1.2亿商品向量全塞进一个索引,没开ANN,P99延迟飙到4.7秒;内容平台上线语义推荐后,CPU常年95%+,运维半夜被告警电话叫醒;还有个金融风控系统,因为每次查询都要扫全量向量,干脆把实时性指标从“毫秒级”悄悄改成了“秒级”。
这些都不是配置调得不够细,而是方向错了:向量检索和关键词检索,是两种完全不同的数学问题。而Elasticsearch原生支持ANN,不是锦上添花的功能,是它能真正扛住生产流量的唯一可行路径。
向量检索的本质,是一场“空间几何战”
我们习惯把文本变成向量,比如用Sentence-BERT把一句话压成768维浮点数组。但这时你要问自己一个问题:
当你说“相似”,你到底在比什么?
关键词检索比的是词是否出现、频次多少、位置远近——这是符号世界的精确匹配,倒排索引干这事就像老司机开车,稳、准、快。
而向量检索比的是两个点在高维空间里的相对位置:它们的方向是否一致?距离是否足够近?这个“近”,可能是余弦夹角小于15度,也可能是欧氏距离小于0.3。它不再关心“有没有这个词”,而是在问:“这句话在语义地图上的坐标,离我有多近?”
这就带来一个致命矛盾:
- 倒排索引擅长处理稀疏、离散、低维的文本特征(比如title: "iPhone");
- 但768维稠密浮点向量,在数学上几乎是“全连接”的——任意两个向量之间都有非零相似度,没有天然的“跳表”或“前缀剪枝”可依赖。
换句话说:你想让Elasticsearch用查“苹果手机”的方式去查“[0.21, -0.87, 0.44, …, 0.19]”,它连刹车片都找不到在哪。
这时候暴力搜索(Brute-Force)就成了唯一“直觉正确”的解法:把查询向量q和库里每个向量v逐一算cosine,取Top-K。听起来很干净?我们来算一笔硬账:
| 规模 | 维度 | 单次计算量(FLOPs) | 1亿条下总计算量 |
|---|