索引层面优化主要包含如下4个方面:索引刷新间隔、索引Schema设置、索引分片数设置和避免Throttling
0 参数修改格式
PUT /${index_name}/_settings?preserve_existing=true
{"refresh_interval": "30s"}
#${index_name} 为需要修改的索引名称
#为了保护现有的设置不被更新,preserve_existing请求参数可以设置为true
#{"refresh_interval": "30s"} 为需要修改的参数复制
1 索引刷新时间
refresh_interval
#默认刷新间隔1s,将会导致大量segment产生,影响性能
#建立大索引时可临时关闭,设置为-1s
#对时效性要求不高的索引(如日志索引),可设置为30s
index.translog.sync_interval
#translog多久被同步到磁盘并提交一次。默认5秒。这个值不能小于100ms
index.translog.durability
#是否在每次index,delete,update,bulk请求之后立即同步并提交translog
#request(默认):每次index,delete,update,bulk请求时就同步一次translog。这就意味着,如果发生崩溃,那么所有只要是已经确认的写操作都已经被提交到磁盘。
#async:在后台每sync_interval时间进行一次fsync和commit。意味着如果发生崩溃,那么所有在上一次自动提交以后的已确认的写操作将会丢失。
index.translog.flush_threshold_size
#默认为512mb。不建议修改
#事务日志存储尚未安全地保留在Lucene中的所有操作(即,不是Lucene提交点的一部分)。尽管可以读取这些操作,但是如果分片已停止并且必须恢复,则需要重播它们。此设置控制这些操作的最大总大小,以防止恢复花费太长时间。一旦达到最大大小,将进行刷新,从而生成新的Lucene提交点。复制
2 索引Schema设置
关联关系
尽量避免使用nested或parent/child;nested query慢;parent/child更慢。
尽量在mapping设计阶段使用大宽表或采用比较SMART的数据结构
若一定要采用nested fields,需要保证该类型字段不能过多,可通过参数(index.mapping.nested_fields.limit)限制,默认50
字段数量
若索引mapping相对固定,可以将dynamic设置为false(检测到新字段不会被索引,但是可以在返回字段中体现)或者strict(检测到新字段,将会报错,文档不会新增)
控制索引中字段数量,可通过配置参数index.mapping.total_fields.limit进行控制,默认1000
控制mapping深度,可以通过配置参数index.mapping.depth.limit进行控制,默认20
字段属性
确定各字段是否需要索引、存储,避免不必要的资源开支;建议id使用ES自动生成;不需要进行聚合、排序和脚本操作的字段关闭doc_value
若使用自定义ID,需要确保分片和路由时数据尽可能均匀的分布在各数据分片上;可以通过选择适合的字段或者优化参数index.routing_partition_size实现
字符串类型,优先选择keyword类型。若需要进行排序及聚合,需要选择keyword;若需要进行分词,需要选择text。
3 索引分片数设置
数据量决定主分片数
数据量较少(规划周期内,数据量少于15G),主分片1个
可避免多数据分片聚合分析导致精准度问题
数据量较多(规划周期内,数据量大于15G),基于以下两点决定
查询要求高(如业务数据),每个数据分片建议控制在10G-15G;数据量过少影响查询精准度;过多影响查询性能
查询要求低(如日志数据),每个数据分片建议控制在30G-50G
数据分片数量需要大于数据节点数量,方便后续的数据节点扩展
数据重要程度、业务中搜索和写入的比重决定副本分片数。副本能提高集群的可用性、增加搜索的并发;但是同时也会影响写入的索引的效率。
高频次的业务数据搜索场景
副本数建议设置为3
日志数据
副本数建议设置为1
4 避免Throttling
每次refresh都产生一个新段(segment),频繁的refresh会导致段数量的暴增。段数量过多会导致过多的消耗文件句柄、内存和CPU时间,影响查询速度。基于这个原因,Lucene会通过合并段来解决这个问题。但是段的合并会消耗掉大量系统资源,尤其是磁盘I/O,所以在Elasticsearch 6.0版本之前对段合并都有“限流(throttling)”功能,主要是为了防止“段爆炸”问题带来的负面影响,这种影响会拖累Elasticsearch的写入速率。
6.X之前(二选一)
通过配置参数(indices.store.throttle.max_bytes_per_sec)提高限流阈值,默认20
通过配置参数(indices.store.throttle.type)为none,关闭限流
6.X及之后
elasticsearch.yml中添加参数(index.merge.scheduler.max_thread_count: 3),该设置允许3+2个线程同时进行磁盘操作;默认Math.min(3, Runtime.getRuntime().availableProcessors() / 2)