最全面的Elasticsearch查询调优

  1. 将内存分配给文件系统缓存
    ​ Elasticsearch严重依赖文件系统缓存来增加搜索速度,我们要尽量确保至少有一半的可用内存进入文件系统,以便Elasticsearch可以将索引的热点区域保留在屋里内存中。

  2. 使用更快的硬件。

  3. 创建合适的文档索引映射
    ​ 避免连接,nested可以使查询慢几倍,父子关系可以使查询慢数百倍,我们可以尽量通过非规范化文档在不连接的情况下回答相同的问题,则可以显著的提升查询速度。

  4. 搜索尽可能搜索较少的字段
    使用query_string,或者multi_match查询目标越多,速度越慢,提高多个字段的搜索速度可以将多个字段的值复制到一个字段中,在搜索时使用该字段。这种方式可以通过copy_to映射指令来执行,而无需改变文档的来源。比如下面的例子:我们创建一个包含电影名称和电影情节还有名称和情节的一个索引。

    PUT movies
    {
      "mappings": {
        "properties": {
          "name_and_plot": {
            "type": "text"
          },
          "name": {
            "type": "text",
            "copy_to": "name_and_plot"
          },
          "plot": {
            "type": "text",
            "copy_to": "name_and_plot"  //{fields}
          }
        }
      }
    }
    //插入一条数据
    PUT movies/_doc/1
    {
      "name":"水门桥很残酷很残酷",
      "plot":"很残酷很残酷"
    }
    //普通情况我们需要查询多个字段是这样写
    GET movies/_search
    {
      "query": {
        "multi_match": {
          "query": "水门桥",
          "fields": ["name","name_and_plot"]
        }
      }
    }
    //当我们简历索引时添加copy_to,我们只需要查询一个字段就可以
    GET movies/_search
    {
      "query": {
        "match": {
          "name_and_plot": "水门桥 很残酷很残酷"
        }
      }
    }
    //查询结果片段
    "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 3.2364235,
        "hits" : [
          {
            "_index" : "movies",
            "_type" : "_doc",
            "_id" : "1",
            "_score" : 3.2364235,
            "_source" : {
              "name" : "水门桥",
              "plot" : "很残酷很残酷"
            }
          }
        ]
      }
    
  5. 预索引数据

    我们可以在你的查询中利用规则来优化数据的索引方式。例如:如果你的文档中包含一个价格字段,并且大多数查询都在固定的范围列表上去聚合,我们可以使用更快的聚合通过将rangs预先写入索引并且通过terms聚合来提升聚合速度。

    例如:创建一个价格索引
    PUT index/_doc/1
    {
      "designation": "spoon",
      "price": 13
    }
    //这时想要查询某个区间的价格数量,需要通过rangs去聚合
    GET index/_search
    {
      "aggs": {
        "price_ranges": {
          "range": {
            "field": "price",
            "ranges": [
              { "to": 10 },
              { "from": 10, "to": 100 },
              { "from": 100 }
            ]
          }
        }
      }
    }
    //如果我们添加一个price_rangs字段创建索引
    PUT index
    {
      "mappings": {
        "properties": {
          "price_range": {
            "type": "keyword"
          }
        }
      }
    }
    //插入一条数据
    PUT index/_doc/1
    {
      "designation": "spoon",
      "price": 13,
      "price_range": "10-100"
    }
    //我们再来求10-100范围内的价格数量,可以使用terms aggregation
    GET index/_search
    {
      "aggs": {
        "price_ranges": {
          "terms": {
            "field": "price_range"
          }
        }
      }
    }
    //聚合结果片段
    "aggregations" : {
        "price_ranges" : {
          "doc_count_error_upper_bound" : 0,
          "sum_other_doc_count" : 0,
          "buckets" : [
            {
              "key" : "10-100",
              "doc_count" : 1
            }
          ]
        }
      }
      
    
  6. 避免使用脚本的排序,聚合中的脚本,和script_source查询

  7. 将mapping类型设置为keyword
    并不是所有数值都可以映射为数值字段类型。Elasticsearch优化数字字段,例如intefer或者long,对于一个range查询,keyword字段更适合term或者其他术语(trem_level)
    如果出现以下情况可以将数值字段映射为keyword类型
    ​ a. 不打算使用range查询来搜索标识符数据(id等,标识符一般使用术语级查询来检索)。
    ​ b. term对字段的查询搜索,keyword要比term对数字字段的搜索要快。

  8. 搜索四舍五入的日期

    使用日期字段now查询通常不会被缓存,因为匹配的范围一直在变化。针对用户体验来说,切换到四舍五入的时间通常是可以接受的,并且有利于更好的利用查询的缓存。

    ps:这个案例还没搞明白,回头补充
    
  9. 预热全局序数(global ordinals)
    全局序数是一种用于优化聚合性能的数据结构。它们是惰性计算的,并作为字段数据缓存的一部分存储在JVM堆中。对于大量用于聚合的字段,你可以告诉Elasticsearch在收到请求之前构造和缓存全局序数。如果使用不当会造成堆使用量增加并且使刷新时间更长。

    //设置全局序数
    PUT {index_name}
    {
      "mappings": {
        "properties": {
          "field_name": {
            "type": "keyword",
            "eager_global_ordinals": true
          }
        }
      }
    }
    
  10. 强制合并只读索引
    只读索引可以合并到单个segment中。这基本是基于时间索引的情况:只有当前时间范围的索引正在获取新文档,而旧索引是只读的。已被强制合并为单个字段的分片可以使用更简单,更有效的数据结构来执行搜索。

  11. 预热文件系统缓存
    如果重新启动运行Elasticsearch的机器,文件系统缓存将是空的,因此操作系统将需要一些时间才能将索引的热点区域加载到内存中,以便快速搜索。可以设置文件扩展名明确告诉操作系统那些文件应该被立即加载到内存。

    PUT /{index_name}
    {
      "settings": {
        "index.store.preload": ["nvd", "dvd","格式"]
      }
    }
    
  12. 用preference优化缓存利用率

  13. 使用更快的短语查询index_phrases

  14. 更快的前缀查询index_prefixes

  15. 用户constant_keyword加速过滤

  16. 禁用swap

  17. 避免深度分页,避免单页数据过大,可以参考百度或者淘宝的做法(归根结底就是不让用户查询到10000条以后的数据)。es提供两种解决方案scroll search和search after

  18. 避免使用稀疏数据

  19. 冷热分离的架构设计

  20. fielddata(jvm):搜索时正排索引,doc_value(disk)为index time正排索引,(一般用于聚合查询)。

  21. enabled:是否创建倒排索引

  22. doc_values:正排索引,对于不需要聚合的字段,关闭正排索引可节省资源,提高查询速度

  23. 开启自适应副本选择(ARS),6.1版本支持,7.0默认开启。

参考文献:
https://www.elastic.co/guide/en/elasticsearch/reference/7.13/tune-for-search-speed.html# 调整搜索速度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值