查询性能调优建议
在查询中提供明确的超时
几乎所有的Elasticsearch API都允许用户指定超时。
找出并摆脱耗时长的操作,节省相关资源,建立稳定的服务,这将对你的应用程序和Elasticsearch集群都有帮助。
谨慎使用Scan和Scroll
Elasticsearch默认只支持查询最多10000条记录,from+size不能大于10000。这种深度分页会随着请求的页次增加,所消耗的内存和时间的增长也是成比例的增加。
深分页场景可以使用Scan或者Scroll,但是谨慎使用Scan和Scroll,因为滚动上下文代价很高,建议不要将其用于实时用户请求,对于大索引,频繁的Scan和Scroll对Elasticsearch集群的稳定性影响非常大,可能会导致jvm假死等甚至宕机等恶劣结果发生。
- 针对实时场景:禁止掉
- 针对离线场景:谨慎使用
使用size:0和includes/excludes限定字段返回
Elasticsearch在添加size:0子句前后会带来显著的性能差异 。
除非业务需要,才返回必要字段,否则,无需返回的字段通过includes和excludes控制。
API调用使用rest接口,慎用transport方式
Elasticsearch的客户端api,native-api支持transport方式访问集群,该方式跟集群内部通信采用统一的基于netty方式通信,持续性写入系统可以采用transport方式。正常的客户端进行索引的查询,使用基于dsl方式的restful接口即可,httpclient访问效率更高。
避免前缀模糊匹配
Elasticsearch 默认支持通过 *? 正则表达式来做模糊匹配,如果在一个数据量较大规模的索引上执行模糊匹配,尤其是前缀模糊匹配,通常耗时会比较长,甚至可能导致内存溢出。尽量避免在高并发查询请求的生产环境执行这类操作。
某客户需要对车牌号进行模糊查询,通过查询请求 "车牌号:A8848" 查询时,往往导致整个集群负载较高。通过对数据预处理,增加冗余字段 "车牌号.keyword",并事先将所有车牌号按照1元、2元、3元...7元分词后存储至该字段,字段存储内容示例:沪,A,8,4,沪A,A8,88,84,48,沪A8...沪A88488。通过查询"车牌号.keyword:A8848"即可解决原来的性能问题。
避免查询深度翻页
Elasticsearch 默认只允许查看排序前 10000 条的结果,当翻页查看排序靠后的记录时,响应耗时一般较长。使用 search_after 方式查询会更轻量级,如果每次只需要返回 10 条结果,则每个 shard 只需要返回 search_after 之后的 10 个结果即可,返回的总数据量只是和 shard 个数以及本次需要的个数有关,和历史已读取的个数无关。
使用search_after、from&size、scroll的一些说明:
- 使用search_after时 from设置为0,-1或者直接不加from
- 使用search_after 进行分页 相比from&size的方式要更加高效,而且在不断有新数据入库的时候仅仅使用from和size分页会有重复的情况
- 相比使用scroll分页,search_after可以进行实时的查询
- search_after不适合跳跃式的分页
配置查询聚合节点
查询聚合节点可以发送粒子查询请求到其他节点,收集和合并结果,以及响应发出查询的客户端。通过给查询聚合节点配置更高规格的 CPU 和内存,可以加快查询运算速度、提升缓存命中率。
某客户使用 25 台 8 核 CPU32G 内存节点 Elasticsearch 集群,查询 QPS 在 4000 左右。增加 6 台 16 核 CPU32G 内存节点作为查询聚合节点,观察服务器 CPU、JVM 堆内存使用情况,并调整缓存、分片、副本参数,查询 QPS 达到 12000。
具体配置如下
# 查询聚合节点配置(conf/elasticsearch.yml): node.master: false node.data: false node.ingest: false 复制代码
配置合适的分词器
Elasticsearch 内置了很多分词器,包括 standard、cjk、nGram 等,也可以安装自研/开源分词器。根据业务场景选择合适的分词器,避免全部采用默认 standard 分词器。
常用的分词器如下:
- standard:默认分词,英文按空格切分,中文按照单个汉字切分。
- cjk:根据二元索引对中日韩文分词,可以保证查全率。
- nGram:可以将英文按照字母切分,结合ES的短语搜索(match_phrase)使用。
- IK:比较热门的中文分词,能按照中文语义切分,可以自定义词典。
- pinyin:可以让用户输入拼音,就能查找到相关的关键词。
- aliws:阿里巴巴自研分词,支持多种模型和分词算法,词库丰富,分词结果准确,适用于电商等对查准要求高的场景。
其他优化建议
不同的业务场景进行集群级别隔离
不要将不同业务场景的数据都放到一个Elasticsearch集群中,建议实时业务和离线业务分开部署。
因为Elasticsearch集群的读写参数配置是所有索引共享的,高峰期会存在相互影响。
建议根据读写频率和实时性要求不同,划分不同的集群进行隔离,根据不同的业务场景设置集群参数!
禁止存放大文本或者二进制数据
Elasticsearch支持大文本和二进制数据,但是大文本和二进制数据会占用集群的内存和磁盘空间,影响集群的磁盘io和缓存效率。
建议将大文本或者二进制数据单独存储在其他的文件系统或者存储系统,然后通过Elasticsearch存放大文本或者二进制数据的存放位置。
命名规范
Elasticsearch的索引命名禁止使用.开始的索引名称,默认Elasticsearch内部或者stack相关组件使用.开始的索引名称。
字段名称禁止使用_开始的索引名称,默认Elasticsearch内部使用的字段名称使用_开始。
索引名称不区分大小写,建议全部由字母、数字组成,字母开头。
同时,索引名称字符长度不要超过32位,字段名称字符长度不要超过32位。