zoukankan      html  css  js  c++  java
  • Elasticsearch优化一

    一、 索引优化

    1. 批量写入
    2. 多线程写入,写入线程数一般和机器数相当
    3. 尽量避免使用nested或 parent/child,能不用就不用;
    4. 如果一定要使用nested fields,保证nested fields字段不能过多,目前ES默认限制是50。
    5. 避免使用动态值作字段(key),动态递增的mapping,会导致集群崩溃;
    6. 不需要做模糊检索的字段使用 keyword类型代替 text 类型, 
    7. 对于那些不需要聚合和排序的索引字段禁用Doc values。

    例如:PUT my_index

    {

      "mappings": {

        "my_type": {

          "properties": {

            "mystring": {

              "type": "keyword",

              "doc_values": false

            }

          }

        }

      }

    }

    消极影响:sort、aggregate、access the field from script将会无法使用

    积极影响:节省磁盘空间

    1. 尽量使用keyword替代一些long或者int之类,term查询总比range查询好
    2. 关闭不需要查询字段的_source功能,不将此存储仅ES中,以节省磁盘空间。

    例如:

    PUT index

    {

      "mappings": {

        "_source": {

    "enabled":false //全部关闭

    "includes": ["field1", "field2"], // 包含的字段

    "excludes": ["field3", "field4"]  // 不包含的字段

        }

      }

    }

    1. 评分消耗资源,如果不需要可使用filter过滤来达到关闭评分功能,score则为0,如果使用constantScoreQuery则score为1。

    当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,

    可以使用constant_score将查询语句query或者过滤语句filter包装起来。

     

    {

        "query":{

            "bool":{

                "should": [

                    { "constant_score": {

                          "query": { "match": { "description": "wifi" }}

                    }},

                  ]

            }

        }

    }

    因为不考虑检索词频率,所以匹配文档的score等于该文档含有的不同检索词汇的个数

     

    二、 查询优化

    1. 使用批量请求,批量索引的效率肯定比单条索引的效率要高。
    2. query_string 或 multi_match 的查询字段越多, 查询越慢。可以在 mapping 阶段,利用 copy_to 属性将多字段的值索引到一个新字段,multi_match时,用新的字段查询。
    3. 日期字段的查询, 尤其是用now 的查询实际上是不存在缓存的,因此, 可以从业务的角度来考虑是否一定要用now, 毕竟利用 query cache 是能够大大提高查询效率的。
    4. 查询结果集的大小不能随意设置成大得离谱的值, 如query.setSize不能设置成 Integer.MAX_VALUE, 因为ES内部需要建立一个数据结构来放指定大小的结果集数据。
    5. 尽量避免使用 script,万不得已需要使用的话,选择painless & experssions 引擎。一旦使用 script 查询,一定要注意控制返回,千万不要有死循环(如下错误的例子),因为ES没有脚本运行的超时控制,只要当前的脚本没执行完,该查询会一直阻塞。如:{ “script_fields”:{ “test1”:{ “lang”:“groovy”, “script”:“while(true){print 'don’t use script'}” } } }
    6. 避免层级过深的聚合查询, 层级过深的group by , 会导致内存、CPU消耗,建议在服务层通过程序来组装业务,也可以通过pipeline 的方式来优化。
    7. 复用预索引数据方式来提高 AGG 性能:  如通过 terms aggregations 替代 range aggregations, 如要根据年龄来分组,分组目标是: 少年(14岁以下) 青年(14-28) 中年(29-50) 老年(51以上), 可以在索引的时候设置一个age_group字段,预先将数据进行分类。从而不用按age来做range aggregations, 通过age_group字段就可以了。
    8. Cache的设置及使用:

      a) QueryCache: ES查询的时候,使用filter查询会使用query cache, 如果业务场景中的过滤查询比较多,建议将querycache设置大一些,以提高查询速度。

      indices.queries.cache.size: 10%(默认),//可设置成百分比,也可设置成具体值,如256mb。

      当然也可以禁用查询缓存(默认是开启), 通过index.queries.cache.enabled:false设置。

      b) FieldDataCache: 在聚类或排序时,field data cache会使用频繁,因此,设置字段数据缓存的大小,在聚类或排序场景较多的情形下很有必要,可通过indices.fielddata.cache.size:30% 或具体值10GB来设置。但是如果场景或数据变更比较频繁,设置cache并不是好的做法,因为缓存加载的开销也是特别大的。

      c) ShardRequestCache: 查询请求发起后,每个分片会将结果返回给协调节点(Coordinating Node), 由协调节点将结果整合。

     

      如果有需求,可以设置开启; 通过设置index.requests.cache.enable: true来开启。

     

      不过,shard request cache 只缓存 hits.total, aggregations, suggestions 类型的数据,并不会缓存hits的内容。也可以通过设置indices.requests.cache.size: 1%(默认)来控制缓存空间大小

       9. 带routing查询

      直接根据 routing 信息定位到某个分配查询,不需要查询所有的分配,经过协调节点排序。

      分片计算:shard = hash(routing) % number_of_primary_shards

      routing 默认值是文档的 id,也可以采用自定义值,比如用户 id。

     

    三、 配置优化

     

    1、不同分片之间的数据同步是一个很大的花费,默认是1s同步,如果我们不要求实时性,我们可以执行如下:

    put /index

    {

        "settings" : {

            "index" : {

             "refresh_interval":"60s"

            }

        }

    }'

     

     此处我们是修改为60s 其实可以改为-1s为不刷新,

     

    2、合理分片

    一般以(节点数*1.5或3倍)来计算,比如有4个节点,分片数量一般是6个到12个,每个分片一般分配一个副本

    分片设置:

    PUT /index

    {

       "settings" : {

          "number_of_shards" : 12,

          "number_of_replicas" : 1

       }

    }

    修改分片的副本数量

    PUT /index/_settings

    {

       "number_of_replicas" : 2

    }

    ES 的每个分片(shard)都是lucene的一个index,而lucene的一个index只能存储20亿个文档,所以一个分片也只能最多存储20亿个文档。

    另外,我们也建议一个分片的大小在10G-50G之间,太大的话查询时会比较慢,

    另外在做副本修复的时,耗时比较多;

    分片太小的话,会导致一个索引的分片数目很多,查询时带来的 fanout 太大。

     

    ElasticSearch推荐的最大JVM堆空间是30~32G, 所以把你的分片最大容量限制为30GB,

     

    3、优化es的线程池

     

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

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

     

    线程池

    作用

    类型

    默认size

    默认队列size

    index

    索引和删除操作

    fixed

    可用处理器的数量

    300

    search

    搜索和计数请求

    fixed

    可用处理器的数量*3

    1000

    suggest

    建议器请求

    fixed

    可用处理器的数量

    1000

    get

    实时的GET请求

    fixed

    可用处理器的数量

    1000

    bulk

    批量操作

    fixed

    可用处理器的数量

    50

    percolate

    预匹配器操作

    fixed

    可用处理器的数量

    1000

     

    elasticsearch.yml中可以设置 :

    threadpool.index.type: fixed

    threadpool.index.size: 100

    threadpool.index.queue_size: 500

     

    当然可以restAPI设置

     

    PUT /_index/settings

    {

        "transient": {

            "threadpool.index.type": "fixed",

            "threadpool.index.size": 100,

            "threadpool.index.queue_size": 500

        }

    }'

     

    4、禁止swap,不让JVM写入swapping,避免降低ES的性能, 

    在elasticsearch.yml 中 bootstrap.memory_lock: true。

     

     

    四、硬件优化

     

    1、当机器内存小于64G时,遵循通用的原则,50%给ES,50%留给lucene

     

    2、磁盘方面配置SSD,机械盘做阵列RAID5 RAID10虽然看上去很快,但是随机IO还是SSD好。

     

    3、使用多块硬盘,并允许 Elasticsearch 通过多个 path.data 目录配置把数据条带化分配到它们上面。

     

    4、不要使用远程挂载的存储,比如 NFS 或者 SMB/CIFS。这个引入的延迟对性能来说完全是背道而驰的。

     

    4、使用自动生成的ID,[自定义的KEY,为了能根据rowkey删除和更新数据]

     

    5、关于段合并,合并在后台定期执行,比较大的segment需要很长时间才能完成,为了减少对其他操作的影响(如检索),elasticsearch进行阈值限制,默认是20MB/s,

     

    可配置的参数:

    "indices.store.throttle.max_bytes_per_sec" : "200mb"  (根据磁盘性能调整)

    合并线程数默认是:

    Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2)),

    如果是机械磁盘,可以考虑设置为1:

    index.merge.scheduler.max_thread_count: 1,

  • 相关阅读:
    node js 修改js代码自动发布到服务器
    NodeJS创建 HTTP 服务器
    node.js安装环境的检查和配置
    JQuery中extend使用
    DataTable 转换为List
    sql 修改表结构 schema
    iOS自动处理键盘事件的第三方库:IQKeyboardManager
    IOS8下的远程推送(转载)
    OC中运行出错( Unknown class <XXX> in InterfaceBuilder file.) 解决办法
    UISegmentedControl
  • 原文地址:https://www.cnblogs.com/L-moye/p/13026041.html
Copyright © 2011-2022 走看看