ES 7.10.2 嵌套字段inner_hits结合stored_fields查询性能咨询
性能开销结论
在7.10.2版本下,命中2000万条记录时使用嵌套inner_hits查询会产生非常明显的性能下降,开销不可忽略,核心原因如下:
- 嵌套文档本质是独立的Lucene文档,和根文档关联存储在同一个Block中。每命中一条根文档,ES都需要额外检索对应关联的嵌套文档子集,这个过程会产生额外的CPU、IO开销。
- 你的场景下禁用了
_source,所有字段都通过store=true单独存储,原本_source可以单次读取整块解压获取全量字段,现在stored_fields需要逐个字段单独读取,inner_hits中读取嵌套存储字段相当于多了一轮随机读开销,比开启_source的场景性能损耗更高。 - 2000万的命中规模会放大单条开销:就算单条根文档的inner_hits处理耗时仅0.1ms,2000万条的总处理耗时也会达到2000s,同时还会带来节点内存占用升高、GC频繁等衍生问题,如果涉及深度分页/全量遍历,开销还会进一步提升。
优化建议
- 如果不需要高频对嵌套层级做独立过滤,可以把需要返回的嵌套字段冗余存储为根文档的普通stored字段,完全规避inner_hits开销,是性能提升最明显的方案。
- 如果必须保留嵌套结构+inner_hits查询,不要一次性拉取2000万条结果,改用
scroll或者search_after做分批拉取,单批次大小控制在1000~5000条,避免单次请求压力过高导致节点异常。 - 针对高频访问的嵌套字段,可以提前触发索引预热,将对应存储字段的内容加载到文件系统缓存中,降低随机读的IO延迟。
内容的提问来源于stack exchange,提问作者Nishikant Tayade
相关产品推荐
相关产品推荐

