elasticsearch 查询优化建议

最近在做一些索引相关的优化测试,顺便记录一下测试以及效果

1:优化mapping  主要包括  doc_values , index  , norms  , type的keyword和text  // 效果明显

doc_values属性  用于把数据序列化到磁盘,使索引结构更紧密

                默认为true,binary类型为false

                缺点:产生额外磁盘消耗

index 属性 用于是否对数据索引,对于一些没必要的数据不必要进行索引检索

                默认都为true

                缺点:对与无索引的对象无法使用条件过滤和查询

norms属性

              不必要聚合的属性可以设置为false


keyword和text是String的拓展,5X之后使用这两个属性

                keyword属性为对数据不建倒排类似以前的String: { "index": "not_analyzed"},text为对数据进行分词倒排

效果:能极大的减少磁盘空间

2 :  禁用 查询中的 _all , 设置合理的shard分片数 ,使用segment段落合并  // 效果明显

_all 默认打开,会把所有字段都在拷贝到这里,增加磁盘使用和影响查询性能

创建索引时添加 "_all":{"enabled":false} 

shard 

一个Shard就是一个Lucene实例,是一个完整的搜索引擎。

分片数过多会导致检索时打开比较多的文件,多台服务器之间通讯成本加大。

而分片数过少会导至单个分片索引过大,所以检索速度也会慢。

建议单个分片最多存储10G-20G左右的索引数据,每个实例的每个索引分片数建议在1-2个左右,并且尽量集群的所有节点

都分片数一致,不要出现分片数不一样导致的一个实例负载过大,等待合并的时间变长;

shard副本

使用副本的优点:数据备份,提高对大索引的查询效率,建议副本在1-2个左右,过多的副本会延迟合并时间以及磁盘使用率提高,性价比不高

segments

每个分片包含多个segment,每一个segment都是一个倒排索引;在查询的时,会把所有的segment查询结果汇总归并后最为最终的分片查询结果返回; segment越多,加载到内存中的segment越多,占用segment memory越多,查询性能可能就会下降,因此应该合并小的segment,减小segment数,提高检索的segment数来提高查询效率

创建索引的时候,elasticsearch会把文档信息写到内存bugffer中,elasticsearch定期会执行flush操作,把segment持久化到磁盘上,索引越大,segment越多,查询效率就会下降,由于segment创建是只是写入缓存,这时期容易系统异常容易丢失数据,可手动执行_flush来实现段落持久化

---- 合并索引段落语句

curl -XPOST 'http://localhost:9200/{_index}/_forcemerge?max_num_segments=1'

----并且每个es实例不要超过32G的jvm内存

---------------------以上策略 能提高不少的查询效率

3:避免内存交换 ,bootstrap.mlockall设置为true来实现  // 意义不大,或许是测试数据集1000w不够大,无法实现

在elasticsearch.yml里添加

bootstrap.memory_lock: true

    1./etc/security/limits.conf ,不限制Es启动用户(如xxx)的memlock
                xxx soft memlock unlimited
                xxx hard memlock unlimited
     2.修改:/etc/sysctl.conf

                vm.swappiness=0   

      ---------延迟刷新时间或禁用刷新
               curl -XGET 'localhost:9200/novehicle-new/_settings' -d '{"refresh_interval": -1}'

4 : 优化query,查询的query返回必要字段,不用的字段,减小返回值大小     

5:优化日志输出等级,把trance改成info   // 好像效果不大

6: 路由优化  // 还在测试

 ES中所谓的路由和IP网络不同,是一个类似于Tag的东西。在创建文档的时候,可以通过字段为文档增加一个路由属性的Tag。ES内在机制决定了拥有相同路由属性的文档,一定会被分配到同一个分片上,无论是主分片还是副本。那么,在查询的过程中,一旦指定了感兴趣的路由属性,ES就可以直接到相应的分片所在的机器上进行搜索,而避免了复杂的分布式协同的一些工作,从而提升了ES的性能。于此同时,假设机器1上存有路由属性A的文档,机器2上存有路由属性为B的文档,那么我在查询的时候一旦指定目标路由属性为A,即使机器2故障瘫痪,对机器1构不成很大影响,所以这么做对灾况下的查询也提出了解决方案。所谓的路由,本质上是一个分桶(Bucketing)操作。当然,查询中也可以指定多个路由属性,机制大同小异。

7: 添加查询缓存,和预处理查询  // 测试中

8: 利用磁盘缓存提高检索

磁盘检索速度过慢,对于实时性较高的场景无法运用磁盘检索 ;所以索引处理中,需要把索引文件刷新加载到缓存中 Elasticsearch默认1s的时间间隔,这也就是说相当于是实时搜索的,Elasticsearch也提供了单独的/_reflush接口,用户如果对1s间隔还是不太满意,可以主动调用接口来保证搜索可见。

--- 刷新所有索引POST /_refresh--- 指定索引刷新

  POST /{_index}/_refresh 

   一般来说我们会通过/_settings接口或者定制template的方式,加大refresh_interval参数:

--- 禁用自动refreshPUT /{_index}/_settings{ "refresh_interval": -1 } --- 设置每秒刷新PUT /{_index}/_settings{ "refresh_interval": "1s" }

9:控制translog  

既然refresh只是写到文件系统缓存中,那么最后一步写到实际磁盘又是由什么来控制的呢?如果这期间发生主机错误、硬盘故障等异常情况,数据会不会丢失?这里,其实Elasticsearch提供了另一个机制来控制。Elasticsearch也把数据写入到内存buffer的同时,其实还另外记录了一个treanslog的日志。也就是说,在内存数据进入到buffer这一步骤时,其实还另外记录了一个translog记录。

10:动态关闭不必要的索引   // 好像没太大意义

索引默认处于open状态,处于open状态的索引都会占用内存,对于不必要的索引可以close

curl -XPOST 'http://localhost:9200/{_index}/_close'

11 : 删除索引的注意点   // 测试中

当一个文档被更新,旧版本的文档被标记为删除,新版本的文档在新的段中索引。也许该文档的不同版本都会匹配一个查询,但是老版本会从结果中删除,

还是参与查询,影响检索效率;

删除文档在es时时不会马上删除,而是先生成.del文件,es在检索时会先判断文件是否删除再过滤,这样会降低检索效率,可手动执行删除文档

curl -XPOST 'http://localhost:9200/{_index}/_forcemerge?only_expunge_deletes=true'

12 : 当要导入大量数据时,设置副本为0,之后动态添加副本   // 效率较大

当导入大量索引时,设置了副本数,es会同时打开副本同步,消耗系统资源,同时需要额外提供主副之间的通信

新建索引是可设置副本为0

----设置副本数

curl -XPOST  'http://localhost:9200/{_index}/_settings' -d 

'{"index":{"number_of_replicas":1}}'

13:给文件系统缓存大内存  至少给可用内存的一半到文件系统缓存。

14: 避免链接,嵌套会使查询慢几倍,而亲自关系能使查询慢几百倍,所以如果同样的问题可以通过没有链接的非规范回答就可以提升速度。

15:使用最小的足够用的数值类型

byte,short,integer,long

half_float,float,double

16: 索引缓冲大小

indices.memory.index_buffer_size通常是JVM的0.1,确保他足够处理至多512MB的索引。

17:优化es的线程池 

threadpool.index.type: fixed  

threadpool.index.size: 100  

threadpool.index.queue_size: 500  

18:采用G1垃圾回收机制代替默认CMS

JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"  

JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=200"  

19: 清理掉没用的缓存

# 缓存类型设置为Soft Reference,只有当内存不够时才会进行回收  

index.cache.field.max_size: 50000  

index.cache.field.expire: 10m  

index.cache.field.type: soft  



猜你喜欢

转载自blog.csdn.net/ailice001/article/details/79664455