为什么 Elasticsearch 中高基数字段上的聚合是一个坏主意以及如何优化它

Elasticsearch 是分布式搜索和分析引擎,是满足搜索和聚合需求的最受欢迎的选择。

Elasticsearch 提供了 2 种数据类型来存储字符串值:

  • Text:- 在存储到倒排索引之前对这些内容进行分析,并针对全文搜索进行优化。 文本字段不允许聚合
  • Keyword :- 它们按原样存储在倒排索引中,如果需要,可以在查询期间进行分析。 这些针对聚合进行了优化,因为它们也以柱状方式存储(称为 doc values),以便可以引用单个字段,而无需在内存中加载完整文档

有关 text 及 keyword 搜索的更多比较,请参阅我之前的文章 "Elasticsearch:Text vs. Keyword - 它们之间的差异以及它们的行为方式"。

Elasticsearch 将 keyword 存储为 doc values 中的序数,以获得更紧凑的表示。 这种映射的工作原理是根据每个术语的字典顺序为每个术语分配一个增量整数或"序数(ordinal)"。 该字段的 doc values 仅存储每个文档的序数而不是原始术语,并具有单独的查找结构来在序数和术语之间进行转换。

在聚合期间使用时,序数可以极大地提高性能。 作为术语(terms)聚合的示例,依赖于序数将文档分组到分片级别的存储桶中,然后在跨分片组合结果时将序数转换回其原始术语值。

每个分片包含多个 "段(segements)",其中一个段就是一个倒排索引。 分片中的搜索将依次搜索每个片段,然后将其结果合并到该分片的最终结果中。 当你为文档建立索引时,Elasticsearch 将它们收集在内存中(为了安全起见,收集在 trasaction log 中),然后每隔一秒左右将一个新的小段写入磁盘,并 "刷新" 搜索。这使得新段中的数据对搜索可见(即它们是 "可搜索的")

每个段都定义自己的序数映射,但聚合会跨整个分片收集数据。 因此,为了能够使用序数(ordinals)进行聚合等分片级操作,Elasticsearch 创建了一个称为全局序数(global ordinals)的统一映射。 全局序数映射建立在段序数之上,并通过维护每个段的从全局序数到局部序数的映射来工作。

必须先构建全局序数映射,然后才能在搜索过程中使用序数。 默认情况下,第一次需要全局序数时会在搜索过程中加载映射。 通常,全局序数在加载时间和内存使用方面不会产生很大的开销。 但是,对于具有大分片的索引,或者如果字段包含大量唯一术语值,则加载全局序数可能会很昂贵。 由于全局序号为分片上的所有段提供了统一的映射,因此当新段可见时,它们也需要完全重建。

解决方案

聚合提供了一个参数 execution_hint,有助于控制存储桶的收集方式。 它默认为 global_ordinals,但可以设置为 map 来直接使用术语值。 这避免了创建全局序数的麻烦并提高了性能,但仅当很少有文档与查询匹配时才应考虑,否则基于序数的执行模式会明显更快。 默认情况下,仅在对脚本运行聚合时使用 map,因为它们没有序数。它可以指定如下:

json 复制代码
1.  "aggs": {
2.      "make": {
3.        "terms": {
4.          "field": "make",
5.          "execution_hint": "map", 
6.          "size": 10
7.        }
8.      }
9.    }

我们还可以使用 eager_global_ordinals,在这种情况下,全局序数是在刷新分片时构建的。 Elasticsearch 总是在公开索引内容的更改之前加载它们。 这将构建全局序数的成本从搜索时间转移到索引时间。 可以为字段启用它,如下所示:

bash 复制代码
1.  PUT my-index-000001/_mapping
2.  {
3.    "properties": {
4.      "tags": {
5.        "type": "keyword",
6.        "eager_global_ordinals": true
7.      }
8.    }
9.  }

可以通过更新 eager_global_ordinals 设置随时禁用预加载:

bash 复制代码
1.  PUT my-index-000001/_mapping
2.  {
3.    "properties": {
4.      "tags": {
5.        "type": "keyword",
6.        "eager_global_ordinals": false
7.      }
8.    }
9.  }
相关推荐
IT成长日记3 小时前
Elasticsearch安全加固指南:启用登录认证与SSL加密
安全·elasticsearch·ssl
Elasticsearch4 小时前
现在支持通过 EDOT Collector 在 Kubernetes 上动态发现工作负载
elasticsearch
上等猿1 天前
Elasticsearch笔记
java·笔记·elasticsearch
qq_5470261791 天前
Elasticsearch 评分机制
大数据·elasticsearch·jenkins
yangmf20401 天前
私有知识库 Coco AI 实战(一):Linux 平台部署
大数据·linux·运维·人工智能·elasticsearch·搜索引擎·全文检索
Elastic 中国社区官方博客1 天前
Elasticsearch:理解政府中的人工智能 - 应用、使用案例和实施
大数据·人工智能·elasticsearch·机器学习·搜索引擎·ai·全文检索
Elasticsearch1 天前
RAG vs. Fine Tuning ,一种实用方法
elasticsearch
Elasticsearch1 天前
了解可观察性指标:类型、黄金信号和最佳实践
elasticsearch
IT成长日记1 天前
Elasticsearch安全与权限控制指南
安全·elasticsearch
算家云1 天前
Ubuntu 22.04安装MongoDB:GLM4模型对话数据收集与微调教程
大数据·人工智能·mongodb·ubuntu·elasticsearch·算家云·glm4微调