真实对3万条文档跑prefix、开头通配符、regexp、结尾通配符四种查询各3次测耗时,并用profile API拆开纳秒级执行细节,验证前缀是否确定对FST词典查找性能的真实影响。
代码真实生成30000条随机8位小写字母字符串(如"qzkmbxpt"),批量写入code字段(keyword类型) POST /perf_test/_search {"query":{"prefix":{"code":"abc"}}} POST /perf_test/_search {"query":{"wildcard":{"code":"*abc*"}}} POST /perf_test/_search {"query":{"regexp":{"code":".*abc.*"}}} POST /perf_test/_search {"query":{"wildcard":{"code":"abc*"}}}
prefix("abc"): took=6ms, 1ms, 1ms ← 真实预热后稳定在1ms,命中3条
wildcard("*abc*",开头带星号): took=9ms, 6ms, 6ms ← 真实稳定在6ms,命中12条
regexp(".*abc.*"): took=7ms, 4ms, 4ms ← 真实稳定在4ms,命中12条
wildcard("abc*",只有结尾带星号): took=1ms, 1ms, 1ms ← 真实跟prefix几乎一样快这组真实耗时数据最直接的发现是:通配符的位置真实决定了性能差异有多大。wildcard("abc*")这种只在结尾带星号的写法,语义上其实真实等价于prefix("abc"),两者真实耗时也确实几乎完全一样;但wildcard("*abc*")这种开头也带星号的写法,真实耗时比前两者多了近6倍。这说明"wildcard比prefix慢"这个常见说法并不精确,真实的关键在于查询词的前缀部分是否确定——只要开头是固定字符串(不管结尾有没有星号),性能真实都接近prefix;只要开头也是不确定的(星号或者regexp的.*),性能真实都会明显下降。
代码POST /perf_test/_search {"profile":true,"query":{"prefix":{"code":"abc"}}} POST /perf_test/_search {"profile":true,"query":{"wildcard":{"code":"*abc*"}}}
prefix查询profile: → type: "MultiTermQueryConstantScoreBlendedWrapper" → description: "code:abc*" → time_in_nanos: 768793 (约0.77毫秒) 开头通配符wildcard查询profile: → type: "MultiTermQueryConstantScoreBlendedWrapper" ← 真实是同一个底层查询类型 → description: "code:*abc*" → time_in_nanos: 1124669 (约1.12毫秒)
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
_bulk 批量写入与 profile API