Elasticsearch 8.X 检索实战调优锦囊 001

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Elasticsearch 8.X 检索实战调优锦囊 001

检索锦囊 1:尽可能的使用缓存

对于精准匹配的查询,不关注评分结果,只关注数据是否满足检索需求。

可以考虑用 filter “包裹一层”,如处理时间范围检索,Elasticsearch 能缓存部分结果。但,要说明的是更换时间窗口,换不同时间段检索,原有缓存不起作用。

关于 filter 的缓存效果,官方文档如是说:

“Frequently used filters will be cached automatically by Elasticsearch, to speed up performance.”

即:“频繁的使用过滤器会有自动缓存的“效果”,以提高性能。”

举例如下,“/m”的本质使检索不是具体到某秒的精确值,而是扩展到分钟。

GET kibana_sample_data_flights/_search
{
  "profile": true, 
  "query": {
    "constant_score": {
      "filter": {
        "range": {
          "timestamp": {
            "gte": "now-1h/m",
            "lte": "now/m"
          }
        }
      }
    }
  }
}

加“profile;true”后,看到的检索结果如下。

官方文档解释的不够准确,这里结合 profile:true的结果,解释一下。

  • 起始时间:now-1h/m 为当前时间戳减去1分钟所在分钟的 00 秒的时刻;
  • 结束时间:now为当前时间戳所在分钟的 59秒的时刻。

更为确切的说,时间跨度为 2 分钟了。

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html#_search_rounded_dates

检索锦囊 2:文件系统缓存预热

如果 Elasticsearch 节点重启,文件系统缓存通常是空的。

操作系统需要一些时间才能将索引的热数据加载到内存中,以便快速检索。

我们可以通过如下的设置来告知操作系统哪些文件应立即加载到内存中。

PUT /my-index-000001
{
  "settings": {
    "index.store.preload": ["nvd", "dvd"]
  }
}

支持的文件扩展名及释义如下所示。

扩展名 英文释义 详细释义
.nvd Norms data 查询时使用的各种归一化因子数据
.dvd doc values Per-Document Values 用于聚合、排序的正排索引文件
.tim terms dictionaries 单词词典
.doc Frequencies 倒排列表,包含:文档列表及词频
.dim points Point values

注意:index.store.preload 设置为“*”通常没有意义,因为所有文件加载到内存中通常没有用。

而更好的选择可能是将其设置为 ["nvd", "dvd", "tim", "doc", "dim"],也就是包含 Norms data、docvalues、单词字典、倒排索引列表等,这些是搜索和聚合中最重要的部分。

https://lucene.apache.org/core/8_0_0/core/org/apache/lucene/codecs/lucene80/package-summary.html

https://www.shenyanchao.cn/blog/2018/12/04/lucene-index-files/

检索锦囊 3:使用预过滤分片执行检索

大背景是:对于时序数据,可以使用 ilm 索引生命周期管理ilm 索引生命周期管理的前置条件是冷热集群架构。也就是:我们有 rollover 滚动索引机制,可以设置索引在热节点、温节点、冷节点的生存时长。

进一步说,索引不是普通的索引,索引有了时间戳的后缀。这样的好处是:当我们需要检索数据的时候,是可以通过别名等方式物理缩小索引范围区间的。

举个例子:如下图所示,weibo_2527 实际指的是上面的“20190225,20190226,20190227”三个索引,如果只检索这三天的数据,相比于全量数据,weibo_2527别名意味着极大的降低了检索数据样本空间。

但,索引层面还足够大,看上面截图我们知道,每个索引下面又有 N 多分片。能否继续优化,下沉到分片层面进行快速锁定分片执行高效检索呢?

这就用到了 7.4+ 版本才有的新特性:prefilter shard。使用 prefilter shard,Elasticsearch 能够根据我们的请求确定需要查询的分片。

预处理分片的本质如张超老师所讲:“对于 Date 类型的 Range 查询,在对分片执行搜索之前,先检查一下分片是否包括被查询的数据范围,如果查询的范围与分片持有的数据没有交集,就跳过该分片。”本质一句话:有助于避免查询到达不必要的分片。

默认情况下,此预过滤分片阶段在以下情况下执行:

  • 条件一:该请求针对超过 128 个分片。
  • 条件二:请求针对一个或多个只读索引。
  • 条件三:基于创建过索引的字段进行排序。

这点,参考张超老师验证且给出的结论——“pre-filter 最主要的作用不是降低查询延迟,而是 pre-filter 阶段可以不占用 search theadpool(检索线程池),相比于不加这个参数,会减少了检索线程池的占用情况。“

具体使用方式如下所示。

相当于在原来检索的基础上加了:pre_filter_shard_size参数。

POST kibana_sample_data_flights_20220727/_search?pre_filter_shard_size=1000
{
  "query": {
    "range": {
      "timestamp": {
        "gte": "2022-07-01",
        "lte":"2022-07-31"
      }
    }
  }
}

https://easyice.cn/archives/350

检索锦囊 4:合并只读分片

我们发现,除了借助 rollover (ilm 索引生命周期管理)将冷数据索引标记为只读之外,我们还可以强制合并(force merge)一个或多个索引的分片。与磁盘碎片整理类似,此操作在不涉及缓存时可极大地提高了查询性能。经过只读分片的合并,最大响应时间由 30 秒降到了2 秒。

POST /.ds-my-data-stream-2099.03.07-000001/_forcemerge?max_num_segments=1&pretty

https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html#forcemerge-api-time-based-index-ex

检索锦囊 5:新建索引时配置排序方式

在 Elasticsearch 中创建新索引时,可以配置指定每个 Shard 中的 Segments 的排序方式。

默认情况下,Lucene 不应用任何排序。index.sort.* 设置定义了应该使用哪些字段来对每个段内的文档进行排序。

举例:如下索引的定义中(篇幅原因,省略了 Mapping),指定了段内基于 timestamp 字段进降序排序。

PUT kibana_sample_data_flights_20220727
{
  "settings": {
    "index": {
      "sort.field": "timestamp",
      "sort.order": "desc",
      "number_of_shards":10,
      "number_of_replicas":0
    }
  },
  "mappings": {
    "properties": {
        ....
        }
      }
   }
 }

同时,有些业务场景,用户不真正关心跟踪命中的总数,并且只希望查询的Top N 个结果。这时候可以基于“提前终止查询”来快速获取检索结果。那么如何做到提前终止查询呢?

我们都知道:Elasticsearch 默认会在 query 阶段查询每个文档,基于给定条件排序后,然后在 fetch 阶段取满足排序条件的结果数据并返回给客户端。

这就意味着分段数越多,排序自然也会越慢,查询的时间越久。

提前终止查询的前置条件是:写入的时候,已经基于字段排序了。假设我们最终期望返回 Top 10 数据,每个分段内各自取 Top 10 然后再整体排序得到 Top 10,不就可以了吗?

打个不恰当的类比,世界杯需要决出前 10 名,那么:亚洲取前10,欧洲取前10,非洲取前10,美洲取前10,整体排序不就是世界足球 Top10了吗?

原理明白了,问题就转化为:如何提前终止呢?

实际上并没有特殊参数控制,因为我们前置设置了:"sort.field": "timestamp", Elasticsearch 会根据 size 大小每个分段取 Top 10 数据后自动终止。

`"track_total_hits": false`的目的是不显示文档总数,这也能降低检索时间,提高检索效率。

执行操作如下所示。

POST _reindex
{
  "source": {
    "index": "kibana_sample_data_flights"
  },
  "dest": {
    "index": "kibana_sample_data_flights_20220727"
  }
}
 
POST kibana_sample_data_flights_20220727/_search
{
  "size": 10,
  "sort": [
    {
      "timestamp": "desc"
    }
  ],
  "track_total_hits": false
}

https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-index-sorting.html#early-terminate

6、小结

  • 在查询中使用近似日期(now/m)而非精准日期格式,以利用节点查询缓存。
  • 时序数据场景,可以将冷数据显示设置为只读来强制执行预过滤分片机制。
  • 必要时对索引执行强制合并(force merge),确保“零碎”的分片合并为一个大分段,以提高检索效率。
  • 关闭超过一年+的索引(具体结合业务需求,如果还在用就不能关),以减少打开的分片数量,避免将资源浪费到无用的数据上。
  • 借助索引生命周期管理 ILM 管理时序数据,实现索引数据的 rollover(滚动),设置只读、强制合并及索引关闭任务,而不是手动执行这种操作。

在“每月存储大约 新增 500 万+数据,每天后端接收 2万次查询请求”的实战业务场景下,如上的优化效果卓著。看对比效果图:

检索对比 平均响应时间(秒) 最长响应时间(秒) 最短响应时间(秒)
优化前 4.619 29.863 0.365
优化后 0.059 1.806 0.010

如上文章翻译自:https://medium.com/teads-engineering/practical-elasticsearch-performance-tuning-on-aws-8c08066e598c

我做了细节展开解读。

你的业务开发或运维中如何做的检索优化呢?欢迎留言讨论交流。

推荐阅读

比同事抢先一步学习进阶干货!


相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
3月前
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
2月前
|
缓存 固态存储 Java
Elasticsearch 的扩展性和性能调优
【9月更文第2天】Elasticsearch 是一个分布式的搜索和分析引擎,适用于各种大规模数据处理场景。随着数据量的增长和查询复杂度的增加,Elasticsearch 的性能优化变得尤为重要。本文将详细介绍如何通过硬件配置、集群规模调整以及查询优化策略来提升 Elasticsearch 的性能。
201 6
|
3月前
|
存储 API 数据库
检索服务elasticsearch索引(Index)
【8月更文挑战第23天】
66 6
|
3月前
|
存储 负载均衡 监控
检索服务elasticsearch节点(Node)
【8月更文挑战第23天】
58 5
|
3月前
|
存储 监控 负载均衡
检索服务elasticsearch集群(Cluster)
【8月更文挑战第23天】
63 3
|
1月前
|
存储 缓存 监控
深入解析:Elasticsearch集群性能调优策略与最佳实践
【10月更文挑战第8天】Elasticsearch 是一个分布式的、基于 RESTful 风格的搜索和数据分析引擎,它能够快速地存储、搜索和分析大量数据。随着企业对实时数据处理需求的增长,Elasticsearch 被广泛应用于日志分析、全文搜索、安全信息和事件管理(SIEM)等领域。然而,为了确保 Elasticsearch 集群能够高效运行并满足业务需求,需要进行一系列的性能调优工作。
82 3
|
2月前
|
存储 自然语言处理 关系型数据库
ElasticSearch基础3——聚合、补全、集群。黑马旅游检索高亮+自定义分词器+自动补全+前后端消息同步
聚合、补全、RabbitMQ消息同步、集群、脑裂问题、集群分布式存储、黑马旅游实现过滤和搜索补全功能
ElasticSearch基础3——聚合、补全、集群。黑马旅游检索高亮+自定义分词器+自动补全+前后端消息同步
|
3月前
|
网络协议 Java API
SpringBoot整合Elasticsearch-Rest-Client、测试保存、复杂检索
这篇文章介绍了如何在SpringBoot中整合Elasticsearch-Rest-Client,并提供了保存数据和进行复杂检索的测试示例。
SpringBoot整合Elasticsearch-Rest-Client、测试保存、复杂检索
|
3月前
|
SQL 存储 自然语言处理
检索服务elasticsearch全文搜索
【8月更文挑战第22天】
55 3
|
3月前
|
SQL 存储 监控
检索服务elasticsearch
【8月更文挑战第21天】
37 0