存储优化

查询优化

索引性能优化

其他优化

 

1. 调大系统的 "最大打开文件数", 例如 65535

 

2. 修改 bin/elasticsearch.in.sh 中的 ES_MIN_MEN 和 ES_MAX_MEN 的大小, 建议设置一样大, 避免频繁的分配内存, 根据服务器内存大小, 一般分配 60% 左右(默认 256M)

  注意: 内存最大不要超过 32G, 是每个实例不要超过 32G, 一个神奇的 32GB 边界值

  https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html#compressed_oops

 

3. 设置 memory_lock 来锁定进程的物理内存地址, 避免交换 (swapped) 来提高性能

  即: conf/elasticsearch.yml -> bootstrap.memory_lock:true

 

4. 设置分片数量, 分片过多或过少, 都会导致检索比较慢

  分片过多会导致检索时打开较多的文件, 另外也会导致多台服务器之间的通讯.

  分片过少, 会导致单个分片索引过大, 所以检索速度也会慢.

  建议单个分片最多存储 20G 左右的索引数据, 所以 分片数量= 数据总量/20G

  或者:  (number_of_shard * (1+number_of_replicas)) < 3*number_of_datanodes

 

5. 副本过多, 可以提升所搜的能力, 但是如果设置很多副本的话, 也会多服务器造成额外的压力, 因为需要主分片需要给所有副本同步数据. 所以建议最多设置 1-2 个即可.

 

6. 要定时对索引进行合并优化, 不然segment越多, 占用的 segment memory 越多, 查询的性能也越差.

curl -XPOST "localhost:9200/_cache/clear" -u elastic
  curl -XPUT 'your-es-host:9200/nginx_log-2018-03-20/_settings' -d '{ "index.merge.scheduler.max_thread_count" : 1 }'

7. 针对不使用的 index, 建议 close, 减少内存占用. 因为只要索引处于 open 状态, 索引库中的 segement就会被占用内存, close之后就只会占用磁盘空间了.

  curl -XPOST 'localhost:9200/zhouls/_close'

 

8. 删除文档: 在 es 中删除文档, 数据不会马上在硬盘上除去, 而是在 es 索引中产生一个 .del 的文件, 而在检索过程中这部分数据也会参与检索, es 在检索过程会判断是否删除了, 如果删除了,在过滤掉. 这样也会降低检索效率. 所以可以定期执行清除删除文档

curl -XPOST 'http://192.168.80.10:9200/zhouls/_forcemerge?only_expunge_deletes=true'
  client.admin().indices().prepareForceMerge("zhouls").setOnlyExpungeDeletes(true).get();
  #清除标记为.del文档
  POST cec_question/_forcemerge?only_expunge_deletes=true

9. 如果在项目开始的时候需要批量入库大量数据的话, 建议将副本数设置为 0, 因为 es 在索引数据的时候, 如果有副本存在, 数据也会马上同步到副本中, 这样会对 es 增加压力. 可以等索引完成后将副本按照需要改回来. 这样可以提高索引效率.

PUT cec_question/_settings
{
"number_of_replicas": 0
}

10. 去掉 mapping 中 _all 字段, Index 中默认会有 _all 这个字段, 默认会把所有字段的内容都拷贝到这一个字段里, 这样会给查询带来方便, 但是会增加索引时间和索引尺寸.

禁用_all字段  "_all":{"enabled":false} 

如果只是某个字段不希望被加到_all中,可以使用 "include_in_all":false

 

11. log 输出的水平默认为 trace, 即查询超过 500ms 即为慢查询, 就要打印日志, 造成 cpu 和 memory, io负载很高. 把log输出的水平改为 info, 可以减轻服务器的压力.

PUT /_cluster/settings
{
"transient": {
"logger.index.search.slowlog":"DEBUG",
"logger.index.index.slowlog":"DEBUG"
}
}

12. 配置 JVM HEAP MAP

修改elasticsearch/jvm.options
  -Xms12g
  -Xmx12g

13. 优化 es 的线程池

  cache: 这是无限制的线程池, 为每个传入的请求创建一个线程.

  fixed: 这是一个有着固定大小的线程池, 大小由 size 属性指定, 允许你指定一个队列 (使用queue_size属性指定) 用来保存请求, 直到有一个空闲的线程来执行请求. 如果elasticsearch 无法把请求放到队列中 (队列满了), 该请求将被拒绝. 有很多线程池 (可以使用 type 属性指定要配置的线程类型), 然而, 对于性能来说,

最重要的是下面几个:

  a. index: 此线程池用于索引和删除操作. 它的类型默认为 fixed, size默认为可用处理器的数量, 队列的size默认为 300.

  b. search: 此线程池用于搜索和计数请求. 它的类型默认为 fixed, size 默认为可用处理器的数量乘以 3, 队列的 size 默认为 1000.

  c. suggest: 此线程池用于建议器请求. 它的类型默认为 fixed, size 默认为可用处理器的数量, 队列的 size 默认为1000.

  d. get: 此线程池用于实时的 GET 请求. 它的类型默认为 fixed, size默认为可用处理器的数量, 队列的 size 默认为 1000.

  e. bulk: 此线程池用于批量操作. 它的类型默认为 fixed, size 默认为可用处理器的数量, 队列的 size 默认为 50.

  f. percolate: 此线程池用于预匹配器操作. 它的类型默认为 fixed, size 默认为可用处理器的数量, 队列的 size 默认为 1000.

 

elasticsearch.yml 中可以设置:
  thread_pool.search.type: fixed
  thread_pool.search.size: 100
  thread_pool.search.queue_size: 500
也可以使用 restAPI 来设置:
curl -XPUT 'localhost:9200/_cluster/settings' -d '{
"transient": {
"thread_pool.search.type": "fixed",
"thread_pool.search.size": 100,
"thread_pool.search.queue_size": 500
}
}'

  注意: 调整 threadpool.size 不要超过core数目, 否则线程之间的 context switching 会消耗掉大量的 cpu 时间, 导致 load 过高. 没有把握勿动. 5.0前后,threadpool 改为 thread_pool

  注意:修改setting后,记得查询是否启用

GET /_cluster/settings?include_defaults=true

 

 

14. 使用 elasticsearch 路由算法, 快速定位数据,提升性能. 缺陷在于每次必须要有一个固定的查询条件, 例如一年的数据, 根据路由进行月份划分, 从而查询时,不需要进行全 shards 进行查询, 可以通过路由来快速确定位置, 前提在于可以明确有一个入参, 但是缺点在于很有可能会造成分片数据存储的不均匀

 

15. 分布式优化:

  a. Elasticsearch 集群角色划分隔离, 把 master 独立出来.

  b. 分片副本策略.

  c. 数据冷热隔离: 一般用户日志型应用, 一般每天创建一个新索引, 当每天的热索引会有比较多的查询, 如果上面还存在比较大的数据, 那么当用户做大跨度的历史数据查询的时候, 过多的磁盘 IO 和 CPU 消耗很容易拖慢写入, 造成数据的延迟. 所以我们用了一部分机器来做冷热数据的存储, 利用 ES 可以给节点配置自定义属性的功能, 为冷接点加上 "boxtype":"weak" 的标识, 每晚通过维护脚本更新冷数据的索引路由设置 index.routing.allocation. {require|include|exclude}, 让数据自动向冷接点迁移. 冷数据的特性是不再写入, 用户查的频率较低, 但量级可能很大.

  d. query优化, 主要就是 query 缓存.

 

16. Lucene 优化

  a. 定期做段合并 (segment)

  b. docValues 相关: Elasticsearch 默认所有字段都开启了 docValues(除了分词), 按照业务酌情关闭部分字段, Elasticsearch Jvm 内存要给系统内存留足够大的空间.

  c. CPU 相关: 屏蔽打分/ 排序机制 tf-idf, 同样的条件, 精确查询速度还没有模糊查询速度快.

  d. IO相关:

  优化 IO, 一次查询, 至少 3 次随机 IO, 预算充足的话, 全部固态硬盘, 次之, tim, doc 文件放到 ssd.

  减少 IO, 使用bool过滤器, 预算判断单词是不是在该索引库里.

 

17. 修改 Translog相关配置

  a. 控制数据从内存到磁盘的操作频率,以减少IO。可以将 sync_interval的时间设置大一些。

    index.translog.sync_interval: 5s(默认)

  b. 控制 translog 数据块的大小,达到 threshold 大小时,才会 flush到 lucene索引文件。

    index.translog.flush_threshold_size: 512(默认)

 

18. _all 字段及 _source 字段的使用,应该注意场景和需要,_all 字段包含了所有的索引字段,方便做全文检索,如果无此需求,可以禁用; _source 存储了原始的 document 内容,如果没有获取原始文档数据的需求,可以通过设置 includes、excludes 属性来定义放入 _source 的字段。

 

19.

bin/elasticsearch.in.sh

ES_MIN_MEN 和 ES_MAX_MEN 的大小, 建议设置一样大 60%

 

 20.配置文件优化

elasticsearch.yml
  bootstrap.memory_lock:true
  indices.breaker.fielddata.limit:60%
  indices.breaker.request.limit:40%
  indices.breaker.total.limit:70%
 
elasticsearch/jvm.options
  -Xms4g
  -Xmx4g

21. bootstrap.memory_lock: true

禁用交换编辑

大多数操作系统都试图使用尽可能多的内存用于文件系统缓存,并急切的交换出未使用的应用程序内存(磁盘内存)。这可能导致部分JVM堆甚至其它执行页面被交换到磁盘上。

交换对性能和节点稳定性非常不利,应该不惜一切代价加以避免。它会导致垃圾回收持续几分钟而不是几毫米(JVM堆在磁盘上导致),并且会导致节点响应缓慢,甚至与集群断开连接。

 

    ((CPU核心数*3)/2)+1设置; 不能超过CPU核心数的2倍;

 

23. 集群调优参数及内存安全:

  merge.scheduler.max_thread_count

  merge.scheduler.max_merge_count 建议 cpu/2, 看机器内存性能 ssd

  index.fielddata.cache: 自定义,与 merge.scheduler.max... 参数相匹配, 通过merge占用内存,剩下内存上限为 fielddata.cache的内存上限, 可用百分百或真实值