为什么 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.  }
相关推荐
Elastic 中国社区官方博客5 小时前
如何将数据从 AWS S3 导入到 Elastic Cloud - 第 3 部分:Elastic S3 连接器
大数据·elasticsearch·搜索引擎·云计算·全文检索·可用性测试·aws
掘金-我是哪吒5 小时前
微服务mysql,redis,elasticsearch, kibana,cassandra,mongodb, kafka
redis·mysql·mongodb·elasticsearch·微服务
研究是为了理解7 小时前
Git Bash 常用命令
git·elasticsearch·bash
晨欣10 小时前
Elasticsearch和Lucene之间是什么关系?(ChatGPT回答)
elasticsearch·chatgpt·lucene
筱源源16 小时前
Elasticsearch-linux环境部署
linux·elasticsearch
Elastic 中国社区官方博客1 天前
释放专利力量:Patently 如何利用向量搜索和 NLP 简化协作
大数据·数据库·人工智能·elasticsearch·搜索引擎·自然语言处理
Shenqi Lotus1 天前
ELK-ELK基本概念_ElasticSearch的配置
elk·elasticsearch
yeye198912241 天前
10-Query & Filtering 与多字符串多字段查询
elasticsearch
Narutolxy2 天前
精准优化Elasticsearch:磁盘空间管理与性能提升技巧20241106
大数据·elasticsearch·jenkins
谢小涛2 天前
ES管理工具Cerebro 0.8.5 Windows版本安装及启动
elasticsearch·es·cerebro