Elasticsearch是一款流行的分布式开源搜索和数据分析引擎,具备高性能、易扩展、容错性强等特点。它强化了Apache Lucene的搜索能力,把掌控海量数据索引和查询的方式提升到一个新的层次。

本文结合开源社区和阿里云平台的实践经验,探讨如何调优Elasticsearch的性能,提高索引和查询吞吐量。

/ 前文回顾 /

Elasticsearch索引和查询性能调优的21条建议【上】

点击查看大图

查询性能调优建议

01

使用过滤器缓存和分片查询缓存

默认情况下,Elasticsearch的查询会计算返回的每条数据与查询语句的相关度,但对于非全文索引的使用场景,用户并不关心查询结果与查询条件的相关度,只是想精确地查找目标数据。此时,可以通过filter来让Elasticsearch不计算评分,并且尽可能地缓存filter的结果集,供后续包含相同filter的查询使用,提高查询效率。

普通查询

curl -XGET "http://localhost:9200/twitter/_search" -H 'Content-Type: application/json' -d'
{"query": {"match": {"user": "kimchy"}}
}'

过滤器(filter)查询

curl -XGET "http://localhost:9200/twitter/_search" -H 'Content-Type: application/json' -d'
{"query": {"bool": {"filter": {"match": {"user": "kimchy"}}}}
}'

分片查询缓存的目的是缓存聚合、提示词结果和命中数(它不会缓存返回的文档,因此,它只在search_type=count时起作用)。

通过下面的参数我们可以设置分片缓存的大小,默认情况下是JVM堆的1%大小,当然我们也可以手动设置在config/elasticsearch.yml文件里:

indices.requests.cache.size: 1%

查看缓存占用内存情况

(name表示节点名, query_cache表示过滤器缓存,request_cache表示分片缓存,fielddata表示字段数据缓存,segments表示索引段)

curl -XGET "http://localhost:9200/_cat/nodes?h=name,query_cache.memory_size,request_cache.memory_size,fielddata.memory_size,segments.memory&v"

02

使用路由routing

Elasticsearch写入文档时,文档会通过一个公式路由到一个索引中的一个分片上。默认的公式如下:

shard_num = hash(_routing) % num_primary_shards

_routing字段的取值,默认是_id字段,可以根据业务场景设置经常查询的字段作为路由字段。例如可以考虑将用户id、地区作为路由字段,查询时可以过滤不必要的分片,加快查询速度。

写入时指定路由

curl -XPUT "http://localhost:9200/my_index/my_type/1?routing=user1" -H 'Content-Type: application/json' -d'
{"title": "This is a document","author": "user1"
}'

查询时不指定路由,需要查询所有分片

curl -XGET "http://localhost:9200/my_index/_search" -H 'Content-Type: application/json' -d'
{"query": {"match": {"title": "document"}}
}'

返回结果

{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0}......
}

查询时指定路由,只需要查询1个分片

curl -XGET "http://localhost:9200/my_index/_search?routing=user1" -H 'Content-Type: application/json' -d'
{"query": {"match": {"title": "document"}}
}'

返回结果

{"took": 1,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0}......
}

03

强制合并只读索引

关闭历史数据索引

只读索引可以从合并成一个单独的大segment中收益,减少索引碎片,减少JVM堆常驻内存。强制合并索引操作会耗费大量磁盘IO,尽量配置在业务低峰期(例如凌晨)执行。历史数据索引如果业务上不再支持查询请求,可以考虑关闭索引,减少JVM内存占用。

索引forcemerge API

curl -XPOST "http://localhost:9200/abc20180923/_forcemerge?max_num_segments=1"

索引关闭API

curl -XPOST "http://localhost:9200/abc2017*/_close"

04

配置合适的分词器

Elasticsearch内置了很多分词器,包括standard、cjk、nGram等,也可以安装自研/开源分词器。根据业务场景选择合适的分词器,避免全部采用默认standard分词器。

常用分词器:

  • standard:默认分词,英文按空格切分,中文按照单个汉字切分。

  • cjk:根据二元索引对中日韩文分词,可以保证查全率。

  • nGram:可以将英文按照字母切分,结合ES的短语搜索(match_phrase)使用。

  • IK:比较热门的中文分词,能按照中文语义切分,可以自定义词典。

  • pinyin:可以让用户输入拼音,就能查找到相关的关键词。

  • aliws:阿里巴巴自研分词,支持多种模型和分词算法,词库丰富,分词结果准确,适用于电商等对查准要求高的场景。

分词效果测试API

curl -XPOST "http://localhost:9200/_analyze" -H 'Content-Type: application/json' -d'
{"analyzer": "ik_max_word","text":     "南京市长江大桥"
}'

常用中文分词器效果对比

05

配置查询聚合节点

查询聚合节点可以发送粒子查询请求到其他节点,收集和合并结果,以及响应发出查询的客户端。通过给查询聚合节点配置更高规格的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

06

设置查询读取记录条数和字段

默认的查询请求通常返回排序后的前10条记录,最多一次读取10000条记录,通过from和size参数控制读取记录范围,避免一次读取过多的记录。通过_source参数可以控制返回字段信息,尽量避免读取大字段。

查询请求示例

curl -XGET http://localhost:9200/fulltext001/_search?pretty  -H 'Content-Type: application/json' -d '
{"from": 0,"size": 10,"_source": "id","query": {"bool": {"must": [{"match": {"content":"虎嗅"}}]}},"sort": [{"id": {"order": "asc"}}]
}
'

07

设置teminate_after查询快速返回

如果不需要精确统计查询命中记录条数,可以配teminate_after指定每个shard最多匹配N条记录后返回,设置查询超时时间timeout。在查询结果中可以通过“terminated_early”字段标识是否提前结束查询请求。

teminate_after查询语法示例

curl -XGET "http://localhost:9200/twitter/_search" -H 'Content-Type: application/json' -d'
{"from": 0,"size": 10,"timeout": "10s","terminate_after": 1000,"query": {"bool": {"filter": {"term": {"user": "elastic"}}}}
}'

08

避免查询深度翻页

Elasticsearch默认只允许查看排序前10000条的结果,当翻页查看排序靠后的记录时,响应耗时一般较长。使用search_after方式查询会更轻量级,如果每次只需要返回10条结果,则每个shard只需要返回search_after之后的10个结果即可,返回的总数据量只是和shard个数以及本次需要的个数有关,和历史已读取的个数无关。

search_after查询语法示例

curl -XGET "http://localhost:9200/twitter/_search" -H 'Content-Type: application/json' -d'
{"size": 10,"query": {"match": {"message": "Elasticsearch"}},"sort": [{"_score": {"order": "desc"}},{"_id": {"order":"asc"}}],"search_after": [  0.84290016,  //上一次response中某个doc的score"1024"  //上一次response中某个doc的id]
}'

09

避免前缀模糊匹配

Elasticsearch默认支持通过*?正则表达式来做模糊匹配,如果在一个数据量较大规模的索引上执行模糊匹配,尤其是前缀模糊匹配,通常耗时会比较长,甚至可能导致内存溢出。尽量避免在高并发查询请求的生产环境执行这类操作。

某客户需要对车牌号进行模糊查询,通过查询请求"车牌号:*A8848*"查询时,往往导致整个集群负载较高。通过对数据预处理,增加冗余字段"车牌号.keyword",并事先将所有车牌号按照1元、2元、3元...7元分词后存储至该字段,字段存储内容示例:沪,A,8,4,沪A,A8,88,84,48,沪A8...沪A88488。通过查询"车牌号.keyword:A8848"即可解决原来的性能问题。

10

避免索引稀疏

Elasticsearch6.X之前的版本默认允许在一个index下面创建多个type,Elasticsearch6.X版本只允许创建一个type,Elasticsearch7.X版本只允许type值为“_doc”。在一个索引下面创建多个字段不一样的type,或者将几百个字段不一样的索引合并到一个索引中,会导致索引稀疏问题。

建议每个索引下只创建一个type,字段不一样的数据分别独立创建index,不要合并成一个大索引。每个查询请求根据需要去读取相应的索引,避免查询大索引扫描全部记录,加快查询速度。

11

扩容集群节点个数

升级节点规格

通常服务器节点数越多,服务器硬件配置规格越高,Elasticsearch集群的处理能力越强。

在不同节点规模下的查询性能测试

(测试环境:Elasticsearch5.5.3集群,单节点16核CPU、64G内存、2T SSD盘,10亿条人口户籍登记信息,数据大小1TB, 20索引分片)

集群节点数 副本数 10并发检索平均响应时间 50并发检索平均响应时间 100并发检索平均响应时间 200并发检索平均响应时间 200并发QPS 200并发CPU使用率 200并发CPUIO等待
1 0 77ms 459ms 438ms 1001ms 200 16% 52%
3 0 38ms 103ms 162ms 298ms 669 45% 34%
3 2 271ms 356ms 577ms 818ms 244 19% 54%
10 0 21ms 36ms 48ms 81ms 2467 40% 10%

不同集群节点规模写入性能测试

(测试环境:Elasticsearch6.3.2集群,单节点16核CPU、64G内存、2T SSD盘,10亿条人口户籍登记信息,单条记录1KB,数据集大小1TB,20个并发写入线程)

集群节点数 副本数 写入TPS 耗时 集群CPU使用率
10 0 88945 11242s 50%
50 0 180638 5535s 20%

在条件允许的情况下,建议可以通过实际的数据和使用场景测试出适合自己的最佳实践。得益于阿里云Elasticsearch提供的弹性扩容功能,阿里云Elasticsearch用户可以在实际使用时根据情况随时增加磁盘大小、扩容节点个数、升级节点规格。

< END >

喜欢就点个在看 or 转发个朋友圈呗

衣舞晨风

推荐阅读:

  • Elasticsearch集群规模和性能调优

  • ElasticSearch 查询的秘密

  • Elasticsearch索引和查询性能调优的21条建议【上】

Elasticsearch索引和查询性能调优的21条建议【下】相关推荐

  1. 【Elasticsearch】索引和查询性能调优的21条建议-以及调优参数

    文章目录 1.概述 1.Elasticsearch部署建议 1.1. 选择合理的硬件配置:尽可能使用 SSD 1.2. 给JVM配置机器一半的内存,但是不建议超过32G 1.3. 规模较大的集群配置专 ...

  2. SQL Server 执行计划(8) - 使用 SQL 执行计划进行查询性能调优

    在本系列的前几篇文章(见底部索引)中,我们介绍了SQL 执行计划的多个方面,我们讨论了执行计划是如何在内部生成的,不同类型的计划,主要组件和运算符以及如何阅读和分析使用不同工具生成的计划.在本文中,我 ...

  3. iOS应用性能调优的25个建议和技巧【转】

    转载自:http://blog.jobbole.com/37984/ 首页 最新文章 资讯 程序员 设计 IT技术 创业 在国外 营销 趣文 特别分享 更多 > - Navigation - 首 ...

  4. elasticsearch原理_花几分钟看一下Elasticsearch原理解析与性能调优

    基本概念 定义 一个分布式的实时文档存储,每个字段 可以被索引与搜索 一个分布式实时分析搜索引擎 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据 用途 全文检索 结构化搜索 分 ...

  5. elasticsearch(es)在用户画像业务上的应用【elasticsearch(es)性能调优】

    1.关于用户画像 用户画像是以用户为中心,从不同角度抽取信息,抽象成标签.这些标签一般都会很多,针对不同的业务需求.应用场景会刻画不同的标签.可以通过标签来圈选适合的人群,来进行精准投放.广告系统.活 ...

  6. sql查询非11位非数字_非生产环境SQL查询性能调优技巧

    sql查询非11位非数字 It is a common misconception that you need real production data, or production like dat ...

  7. iOS应用性能调优的25个建议和技巧

    写在前面 本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/ ...

  8. MySQL索引原理与性能调优

    MySQL 应该是最流行的后端数据库,尽管 NOSQL 近几年越来越火爆,可是相信大部分架构师还是会选择 MySQL 来做数据存储. 作为一名Java程序员相信MySQL我们都不陌生,但真的了解MyS ...

  9. Mysq查询性能调优

    当一条SQL执行较慢,需要分析性能瓶颈,到底慢在哪? 我们一般会使用Explain查看其执行计划,从执行计划中得知这条SQL有没有使用索引?使用了哪个索引? 但是执行计划显示内容不够详细,如果显示用到 ...

最新文章

  1. 最近面试一个6年 Java程序员,一个问题都答不上!
  2. SQL group by 和 order by 、where、having
  3. 我为什么重新开始学习数学?
  4. leetcode-有效的括号(三种语言不同思路)
  5. RecyclerView的下拉刷新和加载更多 动画
  6. Delphi - SEH研究
  7. 深度阅读之《Mastering Go》
  8. 张小龙做微信公众号APP,对自媒体是祸还是福?
  9. 解决IE6下 position的fixed定位问题
  10. centos更改默认python_CentOS系统python默认版本由python2改为python3
  11. bjca客户端 win10_BJCA证书助手 V2.14.4 官方版
  12. 断面计算土方excel表_Civil 3D工程量计算小技巧,一次打包给你!
  13. 算法-满足条件的数字放在新数组
  14. 万年历matlab算法,万年历算法(万年历算法和分析)
  15. 云龙51单片机视频教程+课件+程序代码+课后作业,零基础入门视频教程 (王云)
  16. Git 2.29.2 64位安装包
  17. 无线路灯项目——SIM900A调试
  18. 在计算机操作中粘贴的快捷键是什么,电脑复制粘贴的快捷键是什么
  19. 解决hashcat报错
  20. SQL“除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效“ 解决方法

热门文章

  1. Qt Quick 3D简介
  2. 在Ubuntu18.04和Ubuntu20.04编译Multi-clock步骤(从安装系统开始)
  3. 要怎样才能撤销公司网站备案
  4. 记一次,1个月前的瓜子二手车面试经历
  5. 一位程序员工作10年总结的13个忠告,却让很多人惋惜
  6. lstrip()和rstrip()
  7. MOVE PROTOCOL全球健康宣言,在运动中踏入Web3
  8. 【UVM源码学习】uvm_spell_chkr
  9. Solidwork许可、许可分析、分析许可
  10. java对字符串归一化_字符串归一化