性能优化
ELK日志处理性能如何提升?CPU、内存占用低如何解决?
回复默认分类 • onionwithhoney 回复了问题 • 1 人关注 • 1 个回复 • 2754 次浏览 • 2023-01-05 14:43
社区日报 第1245期 (2021-11-10)
社区日报 • kin122 发表了文章 • 0 个评论 • 1407 次浏览 • 2021-11-10 09:41
es频繁minor gc日志一直报超时
Elasticsearch • a2dou 回复了问题 • 4 人关注 • 3 个回复 • 4170 次浏览 • 2021-07-23 13:50
es数据量大,如何进行性能优化
Elasticsearch • Memento 回复了问题 • 2 人关注 • 1 个回复 • 2282 次浏览 • 2021-06-10 16:12
数据量大,es性能优化
Elasticsearch • 匿名用户 回复了问题 • 2 人关注 • 2 个回复 • 2133 次浏览 • 2021-05-27 19:25
Filter过滤上下文的性能疑问
Elasticsearch • pony_maggie 回复了问题 • 3 人关注 • 2 个回复 • 1815 次浏览 • 2020-08-09 18:24
elasticsearch totalhits过高影响性能问题
Elasticsearch • byx313 回复了问题 • 2 人关注 • 1 个回复 • 2817 次浏览 • 2020-03-15 23:01
Elasticsearch 聚合查询性能问题
Elasticsearch • laoyang360 回复了问题 • 4 人关注 • 3 个回复 • 5694 次浏览 • 2019-12-09 08:49
ES脚本性能优化一例
Elasticsearch • hufuman 发表了文章 • 0 个评论 • 5922 次浏览 • 2019-11-13 19:48
使用painless脚本为文档自定义打分是很常见的场景,对新人来说也是最容易造成性能问题的地方。本文中使用两个例子简单谈一下脚本性能优化。
目标
ES本身是基于倒排等数据结构实现的查询,因此在做类似Term、Match等可以利用底层数据结构的场景进行查询时,性能是很好的。
脚本和term等查询不一样,无法利用现有的各种数据结构,可以简单理解成循环:
docs = getDocs(xxx); // 获取满足条件的文档列表
for(Doc doc : docs) {
score = getScoreByScript(doc);
}
因此脚本的性能取决于两个地方:脚本的复杂度和满足条件的文档数。
例子1
我们有个场景是查询指定坐标指定范围内的POI列表,例如5公里内的景点列表。
由于我们的距离公式和ES默认的都不一致,如下:
/**
* 计算距离,返回单位:米
*/
public static Double getDistance(Double lat1, Double lng1, Double lat2, Double lng2) {
double diffLon = Math.abs(lng1 - lng2);
if (diffLon > 180)
diffLon -= 360;
return Math.sqrt(Math.pow(diffLon, 2) + Math.pow(lat1 - lat2, 2)) * 110.0 * 1000;
}
所以该同学把这段Java代码转成了Painless,在sort里使用这个该方法计算出距离。上线以后发现ES有了很多慢查询,对应的服务也95线、99线也比较高。
原因是其他脚本没有有效地缩小数据量,导致有几百万的数据需要使用该脚本做距离计算,给ES的CPU造成很大压力,查询性能也比较差。
该例子优化起来很简单,即使用ES自带的distance做较大范围的限制,例如需要5公里的数据,可以用ES的plain距离做限制,再加上之前的自定义脚本逻辑。由于ES的plain距离计算性能好很多,因此经过该过滤以后,自定义脚本的文档量少了很多,因此整体性能有了很大提升。
例子2
有个场景是对文章进行搜索,如果文章关联的城市是指定的几个城市,则给额外的加分。例如:
{
"query": {xxx},
"sort": [
{
"_script": {
"script": {
"source": "def score = 0;def cityIds = doc['cityIds']; def paramCityIds = params.cityIds; for (int i=0; i<cityIds.size(); i++){if (paramCityIds.contains(cityIds[i])){score += 100;}} return score;",
"lang": "painless",
"params": {
"cityIds": [2,1,3]
}
},
"type": "number",
"order": "desc"
}
}
]
}
问题和例子1一样,该功能的性能比较差。虽然脚本简单,但是满足的文档量比较大,带来的计算量也比较多,因此性能上不去。
这是一个比较常见的场景,问题的根源还是对ES的机制不够了解,优化起来也很简单,想办法利用到倒排就可以了。
ES里有个专门针对改场景的查询:constant_score,因此以上查询可以修改为:
{
"query": {
"should": [
{
"constant_score": {
"filter": {
"term": {
"cityIds": 2
}
},
"boost": 5
}
},
{
"constant_score": {
"filter": {
"term": {
"cityIds": 1
}
},
"boost": 5
}
},
{
"constant_score": {
"filter": {
"term": {
"cityIds": 3
}
},
"boost": 5
}
}
]
},
"sort": [
{
"_score": "desc"
]
}
性能即可得到极大改善。
四个节点的ES集群,用logstash导入数据的效率很慢,在此附上详细配置,请各位大神帮我分析一下,到底瓶颈在哪里
Logstash • wzfxiaobai 回复了问题 • 10 人关注 • 10 个回复 • 19539 次浏览 • 2019-10-14 11:04
ES从5.1.1升级到6.7.2,性能显著提高
Elasticsearch • HerbertMahone 回复了问题 • 4 人关注 • 2 个回复 • 3510 次浏览 • 2019-09-13 14:19
elasticsearch性能问题
Elasticsearch • laoyang360 回复了问题 • 3 人关注 • 2 个回复 • 3281 次浏览 • 2019-04-18 20:49
threadpool.bulk.size
Elasticsearch • rochy 回复了问题 • 3 人关注 • 1 个回复 • 2327 次浏览 • 2019-03-25 16:00
Day 4 - PB级规模数据的Elasticsearch分库分表实践
Advent • ouyangchucai 发表了文章 • 4 个评论 • 19804 次浏览 • 2018-12-04 20:50
从2018年7月在开始在某阿里云数据中心部署Elasticsearch软件,到2018年12月共创建了15个集群,服务于客户的文档检索、交通视频检索、地理信息检索、日志安全审计等业务。其中数据规模最大的一个业务,共有800张表,7万亿条数据,每天新增500亿条记录,数据要求存储半年,单条记录大小1KB左右,存储规模约10PB,需要支持1000并发查询。
一、数据存储空间规划。
数据中心能用于搭建Elasticsearch集群的SSD盘共700TB,SATA盘共50PB。根据业务类型、时间范围划分热数据和冷数据,一部分重要数据存储在SSD盘的热数据集群,其它数据存储在SATA盘的冷数据集群。热数据集群主要存储各类实体信息,包括人员、物品、事件、地址、组织数据,以及最新轨迹数据。冷数据集群主要存储历史轨迹信息。热数据和冷数据按照业务拆分多个小集群,每个集群规模保持在50个节点左右,单个集群最大不超过200个节点。利用阿里云平台弹性伸缩的能力,每个Elasticsearch集群可以先从小规模创建,根据资源使用情况来弹性扩展节点规模。
Elasticsearch集群节点配置
二、索引设计。
1.索引别名(alias)。每类数据根据数据源表名建立索引(index),索引中只包含一个类型(type)。配置索引别名(alias),业务上根据别名写入、查询数据,索引重建等数据维护操作可以通过别名切换对业务透明。
2.按时间分表。轨迹类数据按时间(日/月)拆分,每个索引存储数据量保持在1TB(10亿)左右,索引名带上日期/月份后缀,拆分后的索引配置别名区分冷热数据。配置索引模板,指定索引分片数和副本数、字段类型、分词器。配置Linux crontab定时任务,通过shell脚本创建索引。
3.分片(shard)设置。索引按照单个分片10-40GB数据大小设计分片数,数据量少于10GB(1000万)的索引设置1个分片即可,数据量大于1TB(10亿)的索引设置分片数为集群节点数整数倍(例如50个节点的集群配置50个分片)。
4.副本(replica)设置。数据首次批量导入时索引副本数设置为0,快速写入数据。生产环境索引副本数设置为1,避免集群节点故障数据丢失。
三、索引mapping设计。
1.精心设计索引字段类型。在开发环境配置Elasticsearch允许自动创建索引,从数据源每张表取1000条记录批量写入Elasticsearch,自动创建索引mapping,然后再根据业务需要修改mapping配置合适的字段类型,指定字段索引分词器、是否存储、是否索引、是否合并至全文检索字段。 对于数据量大的表尤其要精心设计字段类型,尽量减少索引存储空间占用。在生产环境中建议配置不允许自动创建索引。
2.配置全文检索字段。如果业务需要全文检索,可以配置开启全文字段,同时需要占用更多存储空间;如果业务上只是按字段查询,可以配置禁用全文字段,减少存储空间。Elasticsearch5.X及之前的版本默认启用_all字段,合并所有字段的值。Elasticsearch6.X及之后的版本默认禁用_all字段,可以通过copy_to将多个字段值合并成一个全文字段。对于数据查全率要求高的业务场景,建议对全文字段配置cjk分词器(Elasticsearch和Lucene中自带,对中日韩文进行二元分词的分词器)。
3.通用字段统一命名。各个索引中的姓名、证件号码、时间(开始时间、结束时间)、地点(始发地、目的地)等常用字段统一命名。用户指定证件号、时间范围等精确字段查询条件时,可以使用统一的查询条件并行查询多个索引。
四、分词设置。
1.选择合适的分词器。Elasticsearch中内置了很多分词器:standard、cjk、nGram等,也可以安装ik、pinyin等开源分词器, 可以根据业务场景选择合适的分词器。 常用分词器: standard:Elasticsearch默认分词,英文按空格切分,中文按单个汉字切分。 cjk:根据二元索引(两个相邻的字作为一个词条)对中日韩文分词,可以保证查全率。 NGram:可以将英文按照字母切分,结合Elasticsearch的短语搜索(match_phrase)使用。 ik:比较热门的中文分词,能按照中文语义切分,可以自定义词典。 pinyin:可以让用户输入拼音,就能查找到相关的关键词。 对于查全率要求较高的场景,建议使用cjk分词,同时能支持比较快的响应速度。对于查准率要求较高的场景,建议使用ik分词。
CJK分词和IK分词对比(测试环境:Elasticsearch5.5.3,8335万条人员档案信息,10节点集群,单节点16核CPU、64G内存、2T SSD盘,1个线程批量写入,1个并发查询)
测试分词效果: curl -XPOST "http://localhost:9200/_analyze" -H 'Content-Type: application/json' -d' { "analyzer": "ik_max_word", "text": "南京市长江大桥" }'
2.NGram分词。对于像车牌号之类数字和字母连在一起的字符,默认会被切成一个完整词条,但是业务上又需要支持前缀、后缀模糊匹配,可以根据业务需求进行分词。车牌号建议增加一个分词字段,配置NGram分词器,切分1元至7元的组合。身份证号码建议增加分词字段,根据业务需要切分18位完整词条、前2位(省)、前4位(省市)、前6位(省市区县)、后4位、出生年月日、出生年份、出生年月、出生月日等组合。
3.单字分词。对于像姓名类字段,业务上需要支持完整匹配,又需要支持单字查询。可以配置1个keyword字段(不分词);1个text字段(分词),分词器选择Elasticsearch默认分词器standard,按单个汉字切分。
五、数据写入策略。
1.批量离线数据导入。各类业务数据源主要在数据仓库MaxCompute(原ODPS),为了把表数据从MaxCompute表导入到ElasticSearch集群中, 我们基于MaxCompute MapReduce开发了MaxCompute到ElasticSearch的数据导出作业,通过简单的配置就可以把数据导入到ElasticSearch中。 数据源在关系数据库RDS或者NoSQL的数据,可以通过配置DataWorks(dataX企业版)导入Elasticsearch集群。
2.实时数据导入。实时数据源主要是流式数据服务DataHub, 配置DataHub任务即可同步至Elasticsearch集群。也可以自己开发程序调用DataHub的SDK获取实时数据,经过业务处理后,调用ES Rest Client SDK批量写入Elasticsearch。
3.冷热数据自动迁移。轨迹类实时数据默认先写入热数据集群(SSD盘Elasticsearch集群),对于热数据集群过期的索引(例如1个月前的索引)需要迁移到冷数据集群(SATA盘Elasticsearch)。为了实现数据跨集群迁移,我们开发了snapshot插件将索引备份到对象存储服务OSS或分布式文件系统盘古。配置定时任务,将热数据集群索引备份后,从冷数据集群恢复,然后再删除热集群中的过期索引,保持热数据集群只存储较小规模数据。冷数据集群的索引如果超过半年,则关闭索引,减少JVM堆内存占用。
4.配置索引主键字段。为了保证Elasticsearch集群和数据源记录的一致性,建议所有索引配置主键字段,而不是让Elasticsearch自动生成主键。配置数据业务主键字段作为Elasticsearch主键字段。如果没有主键字段,则将原始数据能确定记录惟一性的几个字段合并为主键,或者将所有字段值合并起来计算MD5值作为主键。
5.配置写入路由。如果业务上需要经常根据某个字段查询,例如用户ID、车牌号等的字段,写入时可以指定路由字段。
6.写入参数调优。调整数据写入任务参数,避免写入操作占用过多磁盘IO和CPU。使用批量请求,配置合理的写入线程数,调大索引刷新时间间隔refresh interval,调整事务日志translog同步策略。
六、数据查询策略。
1.冷热库异步查询。用户输入关键词查询时,优先从热数据集群查询,有结果立即返回,并估算命中记录条数。热数据集群命中结果集不足时,再查询冷数据集群。
2.跨集群搜索。业务上需要多个Elasticsearch集群一起参与检索时,可以通过Cross Cluster Search同时对多个集群发起检索请求合并检索结果。单独创建一个5节点的Cross Cluster,设置远程集群节点信息,用于跨集群搜索,不存储业务数据。
3.快速返回和超时设置。查询请求中设置参数teminate_after指定每个分片(shard)最多匹配N条记录后返回(例如10000),设置查询超时时间timeout(例如10s),避免查询一些宽泛的条件时耗费过多系统资源。
4.查询语法解析。解析用户查询条件,识别用户的查询类型,例如用户输入车牌号、证件号、年龄段等条件时,查询条件改写为字段精确匹配,无法识别的查询条件默认从全文字段匹配。
5.查询条件调优。查询结果不需要相关度排序时使用过滤器(filter),尽量使用路由(routing),设置较少的查询读取记录条数和字段,避免前缀模糊匹配,设置search_after规避深度翻页性能问题。
七、数据写入、查询性能测试。
SSD盘集群写入性能测试(测试环境:Elasticsearch6.3.2集群,单节点16核CPU、64G内存、2T SSD盘,写入10亿条记录,单条记录1KB,副本数为0,1台写入服务器):
SSD盘集群查询性能测试
SATA盘集群写入性能测试(测试环境:Elasticsearch5.5.3集群,单节点56核CPU、128G内存、12块 6T SATA盘,分别写入1亿、3亿、5亿、30亿、300亿条记录,单条记录1KB,0副本,50台写入服务器):
SATA盘集群查询性能测试
参考文档:
- 阿里云Elasticsearch帮助文档 https://help.aliyun.com/product/57736.html
- Elasticsearch参考 https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
- 《Elasticsearch: 权威指南》 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
- 《深入理解Elasticsearch》https://detail.tmall.com/item.htm?id=551001166567
- 《死磕Elasticsearch方法论》https://blog.csdn.net/laoyang360/article/details/79293493
- Elasticsearch索引别名和零停机 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index-aliases.html
- Elasticsearch自动按天创建索引脚本 https://blog.csdn.net/reblue520/article/details/80553317
- Elasticsearch NGram分词器 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html
- Elasticsearch开源权限管理认证插件Search Guard https://github.com/floragunncom/search-guard
- Elasticsearch开源可视化管理插件cerebro https://github.com/lmenezes/cerebro
- Elasticsearch开源SQL插件 https://github.com/NLPchina/elasticsearch-sql
- Elasticsearch快照及恢复 https://help.aliyun.com/document_detail/65675.html
Elasticsearch技术交流钉钉群
ES5.0两台集群在50 query并发量的性能已经较低了,性能怎么去提升呢?
Elasticsearch • weizijun 回复了问题 • 3 人关注 • 2 个回复 • 2418 次浏览 • 2018-11-29 12:44
ELK日志处理性能如何提升?CPU、内存占用低如何解决?
回复默认分类 • onionwithhoney 回复了问题 • 1 人关注 • 1 个回复 • 2754 次浏览 • 2023-01-05 14:43
elasticsearch totalhits过高影响性能问题
回复Elasticsearch • byx313 回复了问题 • 2 人关注 • 1 个回复 • 2817 次浏览 • 2020-03-15 23:01
Elasticsearch 聚合查询性能问题
回复Elasticsearch • laoyang360 回复了问题 • 4 人关注 • 3 个回复 • 5694 次浏览 • 2019-12-09 08:49
四个节点的ES集群,用logstash导入数据的效率很慢,在此附上详细配置,请各位大神帮我分析一下,到底瓶颈在哪里
回复Logstash • wzfxiaobai 回复了问题 • 10 人关注 • 10 个回复 • 19539 次浏览 • 2019-10-14 11:04
ES从5.1.1升级到6.7.2,性能显著提高
回复Elasticsearch • HerbertMahone 回复了问题 • 4 人关注 • 2 个回复 • 3510 次浏览 • 2019-09-13 14:19
ES5.0两台集群在50 query并发量的性能已经较低了,性能怎么去提升呢?
回复Elasticsearch • weizijun 回复了问题 • 3 人关注 • 2 个回复 • 2418 次浏览 • 2018-11-29 12:44
ES集群性能问题,求大神帮忙优化下es写入性能
回复Elasticsearch • Dapor 回复了问题 • 10 人关注 • 5 个回复 • 11702 次浏览 • 2018-10-23 10:50
请教各位,为什么要足够大的内存给Lucene?为什么用SSD可以提高性能
回复Elasticsearch • jianjianhe 回复了问题 • 4 人关注 • 2 个回复 • 5198 次浏览 • 2018-04-12 18:17
社区日报 第1245期 (2021-11-10)
社区日报 • kin122 发表了文章 • 0 个评论 • 1407 次浏览 • 2021-11-10 09:41
ES脚本性能优化一例
Elasticsearch • hufuman 发表了文章 • 0 个评论 • 5922 次浏览 • 2019-11-13 19:48
使用painless脚本为文档自定义打分是很常见的场景,对新人来说也是最容易造成性能问题的地方。本文中使用两个例子简单谈一下脚本性能优化。
目标
ES本身是基于倒排等数据结构实现的查询,因此在做类似Term、Match等可以利用底层数据结构的场景进行查询时,性能是很好的。
脚本和term等查询不一样,无法利用现有的各种数据结构,可以简单理解成循环:
docs = getDocs(xxx); // 获取满足条件的文档列表
for(Doc doc : docs) {
score = getScoreByScript(doc);
}
因此脚本的性能取决于两个地方:脚本的复杂度和满足条件的文档数。
例子1
我们有个场景是查询指定坐标指定范围内的POI列表,例如5公里内的景点列表。
由于我们的距离公式和ES默认的都不一致,如下:
/**
* 计算距离,返回单位:米
*/
public static Double getDistance(Double lat1, Double lng1, Double lat2, Double lng2) {
double diffLon = Math.abs(lng1 - lng2);
if (diffLon > 180)
diffLon -= 360;
return Math.sqrt(Math.pow(diffLon, 2) + Math.pow(lat1 - lat2, 2)) * 110.0 * 1000;
}
所以该同学把这段Java代码转成了Painless,在sort里使用这个该方法计算出距离。上线以后发现ES有了很多慢查询,对应的服务也95线、99线也比较高。
原因是其他脚本没有有效地缩小数据量,导致有几百万的数据需要使用该脚本做距离计算,给ES的CPU造成很大压力,查询性能也比较差。
该例子优化起来很简单,即使用ES自带的distance做较大范围的限制,例如需要5公里的数据,可以用ES的plain距离做限制,再加上之前的自定义脚本逻辑。由于ES的plain距离计算性能好很多,因此经过该过滤以后,自定义脚本的文档量少了很多,因此整体性能有了很大提升。
例子2
有个场景是对文章进行搜索,如果文章关联的城市是指定的几个城市,则给额外的加分。例如:
{
"query": {xxx},
"sort": [
{
"_script": {
"script": {
"source": "def score = 0;def cityIds = doc['cityIds']; def paramCityIds = params.cityIds; for (int i=0; i<cityIds.size(); i++){if (paramCityIds.contains(cityIds[i])){score += 100;}} return score;",
"lang": "painless",
"params": {
"cityIds": [2,1,3]
}
},
"type": "number",
"order": "desc"
}
}
]
}
问题和例子1一样,该功能的性能比较差。虽然脚本简单,但是满足的文档量比较大,带来的计算量也比较多,因此性能上不去。
这是一个比较常见的场景,问题的根源还是对ES的机制不够了解,优化起来也很简单,想办法利用到倒排就可以了。
ES里有个专门针对改场景的查询:constant_score,因此以上查询可以修改为:
{
"query": {
"should": [
{
"constant_score": {
"filter": {
"term": {
"cityIds": 2
}
},
"boost": 5
}
},
{
"constant_score": {
"filter": {
"term": {
"cityIds": 1
}
},
"boost": 5
}
},
{
"constant_score": {
"filter": {
"term": {
"cityIds": 3
}
},
"boost": 5
}
}
]
},
"sort": [
{
"_score": "desc"
]
}
性能即可得到极大改善。
Day 4 - PB级规模数据的Elasticsearch分库分表实践
Advent • ouyangchucai 发表了文章 • 4 个评论 • 19804 次浏览 • 2018-12-04 20:50
从2018年7月在开始在某阿里云数据中心部署Elasticsearch软件,到2018年12月共创建了15个集群,服务于客户的文档检索、交通视频检索、地理信息检索、日志安全审计等业务。其中数据规模最大的一个业务,共有800张表,7万亿条数据,每天新增500亿条记录,数据要求存储半年,单条记录大小1KB左右,存储规模约10PB,需要支持1000并发查询。
一、数据存储空间规划。
数据中心能用于搭建Elasticsearch集群的SSD盘共700TB,SATA盘共50PB。根据业务类型、时间范围划分热数据和冷数据,一部分重要数据存储在SSD盘的热数据集群,其它数据存储在SATA盘的冷数据集群。热数据集群主要存储各类实体信息,包括人员、物品、事件、地址、组织数据,以及最新轨迹数据。冷数据集群主要存储历史轨迹信息。热数据和冷数据按照业务拆分多个小集群,每个集群规模保持在50个节点左右,单个集群最大不超过200个节点。利用阿里云平台弹性伸缩的能力,每个Elasticsearch集群可以先从小规模创建,根据资源使用情况来弹性扩展节点规模。
Elasticsearch集群节点配置
二、索引设计。
1.索引别名(alias)。每类数据根据数据源表名建立索引(index),索引中只包含一个类型(type)。配置索引别名(alias),业务上根据别名写入、查询数据,索引重建等数据维护操作可以通过别名切换对业务透明。
2.按时间分表。轨迹类数据按时间(日/月)拆分,每个索引存储数据量保持在1TB(10亿)左右,索引名带上日期/月份后缀,拆分后的索引配置别名区分冷热数据。配置索引模板,指定索引分片数和副本数、字段类型、分词器。配置Linux crontab定时任务,通过shell脚本创建索引。
3.分片(shard)设置。索引按照单个分片10-40GB数据大小设计分片数,数据量少于10GB(1000万)的索引设置1个分片即可,数据量大于1TB(10亿)的索引设置分片数为集群节点数整数倍(例如50个节点的集群配置50个分片)。
4.副本(replica)设置。数据首次批量导入时索引副本数设置为0,快速写入数据。生产环境索引副本数设置为1,避免集群节点故障数据丢失。
三、索引mapping设计。
1.精心设计索引字段类型。在开发环境配置Elasticsearch允许自动创建索引,从数据源每张表取1000条记录批量写入Elasticsearch,自动创建索引mapping,然后再根据业务需要修改mapping配置合适的字段类型,指定字段索引分词器、是否存储、是否索引、是否合并至全文检索字段。 对于数据量大的表尤其要精心设计字段类型,尽量减少索引存储空间占用。在生产环境中建议配置不允许自动创建索引。
2.配置全文检索字段。如果业务需要全文检索,可以配置开启全文字段,同时需要占用更多存储空间;如果业务上只是按字段查询,可以配置禁用全文字段,减少存储空间。Elasticsearch5.X及之前的版本默认启用_all字段,合并所有字段的值。Elasticsearch6.X及之后的版本默认禁用_all字段,可以通过copy_to将多个字段值合并成一个全文字段。对于数据查全率要求高的业务场景,建议对全文字段配置cjk分词器(Elasticsearch和Lucene中自带,对中日韩文进行二元分词的分词器)。
3.通用字段统一命名。各个索引中的姓名、证件号码、时间(开始时间、结束时间)、地点(始发地、目的地)等常用字段统一命名。用户指定证件号、时间范围等精确字段查询条件时,可以使用统一的查询条件并行查询多个索引。
四、分词设置。
1.选择合适的分词器。Elasticsearch中内置了很多分词器:standard、cjk、nGram等,也可以安装ik、pinyin等开源分词器, 可以根据业务场景选择合适的分词器。 常用分词器: standard:Elasticsearch默认分词,英文按空格切分,中文按单个汉字切分。 cjk:根据二元索引(两个相邻的字作为一个词条)对中日韩文分词,可以保证查全率。 NGram:可以将英文按照字母切分,结合Elasticsearch的短语搜索(match_phrase)使用。 ik:比较热门的中文分词,能按照中文语义切分,可以自定义词典。 pinyin:可以让用户输入拼音,就能查找到相关的关键词。 对于查全率要求较高的场景,建议使用cjk分词,同时能支持比较快的响应速度。对于查准率要求较高的场景,建议使用ik分词。
CJK分词和IK分词对比(测试环境:Elasticsearch5.5.3,8335万条人员档案信息,10节点集群,单节点16核CPU、64G内存、2T SSD盘,1个线程批量写入,1个并发查询)
测试分词效果: curl -XPOST "http://localhost:9200/_analyze" -H 'Content-Type: application/json' -d' { "analyzer": "ik_max_word", "text": "南京市长江大桥" }'
2.NGram分词。对于像车牌号之类数字和字母连在一起的字符,默认会被切成一个完整词条,但是业务上又需要支持前缀、后缀模糊匹配,可以根据业务需求进行分词。车牌号建议增加一个分词字段,配置NGram分词器,切分1元至7元的组合。身份证号码建议增加分词字段,根据业务需要切分18位完整词条、前2位(省)、前4位(省市)、前6位(省市区县)、后4位、出生年月日、出生年份、出生年月、出生月日等组合。
3.单字分词。对于像姓名类字段,业务上需要支持完整匹配,又需要支持单字查询。可以配置1个keyword字段(不分词);1个text字段(分词),分词器选择Elasticsearch默认分词器standard,按单个汉字切分。
五、数据写入策略。
1.批量离线数据导入。各类业务数据源主要在数据仓库MaxCompute(原ODPS),为了把表数据从MaxCompute表导入到ElasticSearch集群中, 我们基于MaxCompute MapReduce开发了MaxCompute到ElasticSearch的数据导出作业,通过简单的配置就可以把数据导入到ElasticSearch中。 数据源在关系数据库RDS或者NoSQL的数据,可以通过配置DataWorks(dataX企业版)导入Elasticsearch集群。
2.实时数据导入。实时数据源主要是流式数据服务DataHub, 配置DataHub任务即可同步至Elasticsearch集群。也可以自己开发程序调用DataHub的SDK获取实时数据,经过业务处理后,调用ES Rest Client SDK批量写入Elasticsearch。
3.冷热数据自动迁移。轨迹类实时数据默认先写入热数据集群(SSD盘Elasticsearch集群),对于热数据集群过期的索引(例如1个月前的索引)需要迁移到冷数据集群(SATA盘Elasticsearch)。为了实现数据跨集群迁移,我们开发了snapshot插件将索引备份到对象存储服务OSS或分布式文件系统盘古。配置定时任务,将热数据集群索引备份后,从冷数据集群恢复,然后再删除热集群中的过期索引,保持热数据集群只存储较小规模数据。冷数据集群的索引如果超过半年,则关闭索引,减少JVM堆内存占用。
4.配置索引主键字段。为了保证Elasticsearch集群和数据源记录的一致性,建议所有索引配置主键字段,而不是让Elasticsearch自动生成主键。配置数据业务主键字段作为Elasticsearch主键字段。如果没有主键字段,则将原始数据能确定记录惟一性的几个字段合并为主键,或者将所有字段值合并起来计算MD5值作为主键。
5.配置写入路由。如果业务上需要经常根据某个字段查询,例如用户ID、车牌号等的字段,写入时可以指定路由字段。
6.写入参数调优。调整数据写入任务参数,避免写入操作占用过多磁盘IO和CPU。使用批量请求,配置合理的写入线程数,调大索引刷新时间间隔refresh interval,调整事务日志translog同步策略。
六、数据查询策略。
1.冷热库异步查询。用户输入关键词查询时,优先从热数据集群查询,有结果立即返回,并估算命中记录条数。热数据集群命中结果集不足时,再查询冷数据集群。
2.跨集群搜索。业务上需要多个Elasticsearch集群一起参与检索时,可以通过Cross Cluster Search同时对多个集群发起检索请求合并检索结果。单独创建一个5节点的Cross Cluster,设置远程集群节点信息,用于跨集群搜索,不存储业务数据。
3.快速返回和超时设置。查询请求中设置参数teminate_after指定每个分片(shard)最多匹配N条记录后返回(例如10000),设置查询超时时间timeout(例如10s),避免查询一些宽泛的条件时耗费过多系统资源。
4.查询语法解析。解析用户查询条件,识别用户的查询类型,例如用户输入车牌号、证件号、年龄段等条件时,查询条件改写为字段精确匹配,无法识别的查询条件默认从全文字段匹配。
5.查询条件调优。查询结果不需要相关度排序时使用过滤器(filter),尽量使用路由(routing),设置较少的查询读取记录条数和字段,避免前缀模糊匹配,设置search_after规避深度翻页性能问题。
七、数据写入、查询性能测试。
SSD盘集群写入性能测试(测试环境:Elasticsearch6.3.2集群,单节点16核CPU、64G内存、2T SSD盘,写入10亿条记录,单条记录1KB,副本数为0,1台写入服务器):
SSD盘集群查询性能测试
SATA盘集群写入性能测试(测试环境:Elasticsearch5.5.3集群,单节点56核CPU、128G内存、12块 6T SATA盘,分别写入1亿、3亿、5亿、30亿、300亿条记录,单条记录1KB,0副本,50台写入服务器):
SATA盘集群查询性能测试
参考文档:
- 阿里云Elasticsearch帮助文档 https://help.aliyun.com/product/57736.html
- Elasticsearch参考 https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
- 《Elasticsearch: 权威指南》 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
- 《深入理解Elasticsearch》https://detail.tmall.com/item.htm?id=551001166567
- 《死磕Elasticsearch方法论》https://blog.csdn.net/laoyang360/article/details/79293493
- Elasticsearch索引别名和零停机 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index-aliases.html
- Elasticsearch自动按天创建索引脚本 https://blog.csdn.net/reblue520/article/details/80553317
- Elasticsearch NGram分词器 https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html
- Elasticsearch开源权限管理认证插件Search Guard https://github.com/floragunncom/search-guard
- Elasticsearch开源可视化管理插件cerebro https://github.com/lmenezes/cerebro
- Elasticsearch开源SQL插件 https://github.com/NLPchina/elasticsearch-sql
- Elasticsearch快照及恢复 https://help.aliyun.com/document_detail/65675.html
Elasticsearch技术交流钉钉群