Elasticsearch,搜索速度极慢

Nee*_*raj 1 performance query-optimization database-performance elasticsearch elastic-stack

我们有一个由 3 个主节点(每个 4 核、16 GB RAM)、3 个热节点(每个 8 核、32 GB RAM、300 GB SSD)和 3 个热节点(每个 8 核、32GB RAM、1.5TB HDD)组成的集群。 。

我们按照 的命名约定为一年中的每个月都有一个索引voucher_YYYY_MMM(eg voucher_2021_JAN)。所有这些索引都有一个voucher充当读取别名的别名,我们的搜索查询针对该读取别名。

我们的索引在热节点上驻留 32 天,在此期间它将接收 99% 的写入。我们估计该索引中的数据约为 4.8 亿个文档,它有 1 个副本和 16 个分片(我们采用了 16 个分片,因为最终我们的数据会增长,现在我们正在考虑缩小到 8 个分片,每个分片有 30 GB数据,根据我们的映射,200 万个文档占用 1GB 空间)。

32天后索引将转移到温节点,目前,我们的热索引中有4.5亿个文档,温索引中有18亿个文档。文档总数达 22.5 亿篇。

我们的文档包含客户 ID 和我们正在应用过滤器的一些字段,它们全部映射为关键字类型,我们用于custom routing on customer id提高搜索速度。

我们典型的查询看起来像

GET voucher/_search?routing=1000636779&search_type=query_then_fetch
{
  "from": 0,
  "size": 20,
  "query": {
    "constant_score": {
      "filter": {
        "bool": {
          "filter": [
            {
              "term": {
                "uId": {
                  "value": "1000636779",
                  "boost": 1
                }
              }
            },
            {
              "terms": {
                "isGift": [
                  "false"
                ]
              }
            }
          ]
        }
      }
    }
  },
  "version": true,
  "sort": [
    {
      "cdInf.crtdAt": {
        "order": "desc"
      }
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我们使用恒定分数查询是因为我们不想对文档进行评分并希望提高搜索速度。

我们的每个热节点和温节点上都有 13 个搜索线程,并且我们正在向主节点发送请求以进行索引和搜索。

我们每秒发送 100 个搜索请求,平均搜索响应时间约为 3.5 秒,其中最长时间可达 9 秒。

我不明白我们错过了什么,为什么我们的搜索性能如此差。

Val*_*Val 5

感谢您的详尽解释。基于它们,这里有几个改进点(排名不分先后):

  1. 永远不要将搜索和索引请求定向到主节点,它们永远不应该处理流量。将它们直接发送到数据节点,或者更好的是发送到专用协调节点。
  2. 直接的结果是,主(合格)节点不需要 16GB RAM,2GB 就足够了,因为它们将不再充当协调节点。
  3. 如果查询中有时间范围,您可以利用字段上的索引排序cdInf.crtdAt。更快的搜索是以更慢的摄取为代价的,但只有当您的查询有时间限制时才有意义,否则就没有意义。
  4. 3 个热节点上每个索引 16 个分片并不是一个好的分片策略,您应该拥有节点数量的倍数(3、6、9 等),否则其中一个节点将拥有更多分片,因此,您可能会创建热点。您还可以再添加一个热节点,这样每个热节点就有 4 个分片。这是过度分片的典型例子。由于索引每月都会滚动,因此当您看到数据增长时,可以轻松修改索引模板中的主分片数量。
  5. 利用路由来搜索更少的分片是个好主意。从问题中不清楚别名后面总共有多少个索引voucher,但这也是一个很好的信息,可以用来评估搜索线程的分片和大小是否合适。根据您提供的文档数量,您似乎有 1 个热索引和 5 个热索引,因此总共有 6 个索引。因此每个带路由的搜索请求只会搜索 6 个分片。
  6. 每秒 100 个搜索请求和每个节点 13 个搜索线程(8 个核心的默认值)意味着每个节点每秒必须处理 7 个以上搜索请求,并且由于请求大约需要 3 秒才能返回,因此您正在构建一个搜索队列,因为节点可能无法跟上。
  7. 为了从过滤器缓存中受益,可以利用的另一个功能是preference查询字符串参数
  8. 另外,速度缓慢的部分原因是您正在搜索的 80% 的数据位于带有旋转磁盘的热节点上,因此根据您的使用情况,您可能希望将搜索分成两部分,即一个超级节点对热数据进行快速搜索,对温数据进行另一个较慢的搜索。
  9. 一旦你的索引被重新分配到热节点(如果它们不再更新),最好将它们强制合并到几个段(3到5),这样你的搜索就可以浏览和浏览更少的段。还可以减小它们的大小(即删除已删除的文档)