在现代数据处理和搜索引擎应用中,Elasticsearch 已成为高效检索和分析数据的重要工具。然而,随着数据量的增长和查询请求的增加,性能问题也随之显现。如何有效优化 Elasticsearch 的性能,确保查询迅速且资源使用均衡,是每位开发者和运维人员面临的挑战。本文将介绍几种实用的 Elasticsearch 性能优化实践,包括节点负载均衡、慢查询处理、合理使用 filter 子句等,帮助您提升 Elasticsearch 的整体性能,实现更快的响应速度和更低的系统负载。
ES 性能优化实践:节点负载不均衡
现象:
每个索引使用默认的 1 个分片,1 个副本,在 3 节点集群出现负载不均衡现象,两个节点 cpu 负载很高,另外一个节点 cpu 负载更低。
原因:
分片+副本一共 2 个,只能被分散到两个节点上,查询请求只能命中这两个节点。
解决方案:
Elasticsearch 创建索引后无法动态修改分片数,但是可以动态修改副本数,增加副本数可以分散查询请求。
在不改变分片数的情况下,通过调整分片的副本数,使分片副本数+原始分片数的总数为节点数基数或倍数,以达到节点负载均衡; 将索引的分片副本数增加到 2,加上分片自身,一共 3 个,刚好均分给 3 个节点,调整后节点 cpu 负载到达均衡。
ES 性能优化实践:慢查询
现象:
一个简单的查询,耗时需要 500ms
查询请求参数中使用 terms 条件查询如下:
{
"terms": {
"my_int_field": [5, 0, 0]
}
}
原因:
生产环境的数据中, my_int_field
字段的默认值为 0,这里需求是查特定非 0 值,由于代码逻辑没有过滤默认值,查询字段中出现 0,导致几乎全部记录被匹配,于是产生了慢查询。
ES 性能优化实践:开启 ES 慢查询日志
Elasticsearch 默认没有开启慢查询日志,需要手动调用 api 进行开启。
如下对全部索引都配置开启慢查询日志:
PUT */_settings
{
"index.indexing.slowlog.threshold.index.debug" : "5ms",
"index.indexing.slowlog.threshold.index.info" : "50ms",
"index.indexing.slowlog.threshold.index.warn" : "100ms",
"index.search.slowlog.threshold.fetch.debug" : "10ms",
"index.search.slowlog.threshold.fetch.info" : "50ms",
"index.search.slowlog.threshold.fetch.warn" : "100ms",
"index.search.slowlog.threshold.query.debug" : "100ms",
"index.search.slowlog.threshold.query.info" : "200ms",
"index.search.slowlog.threshold.query.warn" : "500ms"
}
具体时长可以根据实际情况调整。
ES 性能优化实践:使用 filter 子句优化 bool 查询
默认情况下,Elasticsearch 按相关性分数对匹配的搜索结果进行排序,相关性分数衡量每个文档与查询的匹配程度。
相关性分数是一个正浮点数,在搜索 API 的 _score
元数据字段中返回。 _score
越高,文档越相关。
分数计算决于查询子句是在 query context 中还是在 filter context 中运行。
对于 bool 查询,must
和 should
子句使用 query context,filter
和 must_not
使用 filter context。
query context 关注的是文档的匹配程度,因此查询除了关注文档是否匹配以外还需要计算匹配度得分。
filter context 关注的只是文档是否匹配,没有额外计算,并且 ES 会自动缓存 filter context 的查询结果。
如果只关注是否匹配,尽量使用 filter context 构造查询子句。
ES 性能优化实践:查询性能分析
在 Kibana 的 Dev Tool 中,使用 search profile 可以查看具体耗时分析
从 View details 中可以看到主要耗时是在 should 子句的计算得分
这里的 should 子句在使用 filter context 后,es 会缓存结果,当 3 个节点都有缓存时耗时明显减少,在 console 中进行查询时基本可以在 30 毫秒内返回。
ES 性能优化实践:terms 查询优化
将 terms 替换为多个 term 查询可以提高性能。精确匹配使用 term 查询,不要使用 match 查询。
should 子句中使用了 terms 查询,可以看到耗时较多,类型为 PointInSetQuery,这里主要耗时也是在计算得分。
将 terms 查询条件替换为多个 term 的组合查询,可以看到查询类型变成了 PointRangeQuery 类型,性能又得到了相当大的提升!
term 查询数字类型的值使用 range 查询,查询类型会变成 IndexOrDocValuesQuery,性能可以更进一步提升:
同样的查询场景,耗时从最开始的 270ms->99ms->12ms,性能提升 20 多倍。
Elasticsearch 性能优化 FAQ
1. 什么是 Elasticsearch 性能优化?
Elasticsearch 性能优化是通过各种技术和配置调整来提高查询速度和资源利用效率的过程。这包括节点负载均衡、查询优化和慢查询日志监控等。
2. 如何解决 Elasticsearch 节点负载不均衡问题?
可以通过增加副本数量来实现负载均衡。在不改变分片数量的情况下,确保分片和副本的总数与节点数量相匹配,以均匀分配查询请求。
3. 什么是慢查询,如何识别?
慢查询是指耗时较长的查询操作,通常超过设定的阈值。可以通过开启慢查询日志来监控和识别慢查询,以便后续优化。
4. 使用 filter 子句有什么好处?
使用 filter 子句可以避免不必要的得分计算,提升查询性能。此外,filter 查询结果会被自动缓存,进一步加速后续查询的响应速度。
5. 如何提升 Elasticsearch 查询的整体性能?
提升查询性能的方法包括:
- 增加副本数量以平衡负载。
- 避免在查询中使用默认值,减少匹配记录。
- 替换 terms 查询为多个 term 查询以提高效率。
- 在 Kibana 中使用 search profile 进行性能分析和优化。
小结
通过实施上述 Elasticsearch 性能优化策略,用户可以显著改善系统的查询速度与资源利用效率。无论是调整节点配置、优化查询方式,还是监控慢查询日志,这些实践都将为数据处理带来更高的效率。随着对性能需求的不断提高,持续关注和优化 Elasticsearch 的使用将是确保业务顺利运行的关键。希望本文提供的建议能为您的 Elasticsearch 性能提升提供实用的指导与灵感。