术语聚合性能高基数

Posted

技术标签:

【中文标题】术语聚合性能高基数【英文标题】:Terms aggregation performance high cardinality 【发布时间】:2015-08-02 07:49:59 【问题描述】:

我希望对我最近观察到的 elastic 1.5.2 中的查询性能进行一些澄清。

我有一个高基数的字符串字段(大约 200,000,000)。 我观察到,如果我使用带有执行提示 global_ordinals_low_cardinality 的简单术语聚合,会发生两件事: 1. 查询返回与 global_ordinals 或 global_ordinals_hash 相同的结果。 2. 查询执行速度明显加快。 (大约是 global_ordinals 的两倍,是 global_ordinals_hash 的 4 倍。

这是查询:


   "aggs": 
      "myTerms": 
         "terms": 
            "field": "myField",
            "size": 1000,
            "shard_size": 1000,
            "execution_hint": "global_ordinals_low_cardinality"
         
      
   

我不明白为什么在这种情况下使用 global_ordinals_low_cardinality 是合法的,因为我的字段具有高基数。所以也许我不明白 global_ordinals_low_cardinality 到底是什么意思?

其次,我有另一个数字字段(长),具有大致相同的基数值。 long 字段的值实际上是上面相同字符串字段的预计算哈希值 (murmur3),我用它来大大加快基数聚合。 在数值字段上运行相同的术语聚合与 global_ordinals_hash 一样糟糕。 其实不管我用什么执行提示,执行时间都是一样的。

那么为什么 global_ordinals_low_cardinality 适用于字符串类型,但不适用于长类型?是因为数值字段根本不需要全局序数吗?

谢谢

【问题讨论】:

【参考方案1】:

我认为official documentation 和源代码都对此有所了解。首先,需要提到的一件事是execution_hint 正是它的名字所说的,即只是一个提示 ES 将尝试尊重,但如果它认为不是,则可能并非在所有情况下合适。

因此,仅凭您具有高基数字段这一事实就无法使用global_ordinals_low_cardinality,因为:

global_ordinals_low_cardinality 默认情况下仅在低基数字段上启用。

至于global_ordinals_hash,它主要用于内部术语聚合(这里不是这种情况),而map仅在对脚本运行聚合并且很少有文档匹配查询时使用(也不是cas)

因此,您只有一个选择,即global_ordinals,这是***术语聚合中使用的默认提示。

如前所述,execution_hint 只是您指定的提示,但无论如何 ES 都会尽力为您的数据选择正确的执行模式。查看源代码很有启发性,并阐明了一些事情:

Starting here,你会看到:

    on line 201,您的提示已被读取,如果该字段不支持全局序数,则可能会被覆盖 (lines 205-241) 如果您的field is numeric、execution_hint 被完全忽略,这应该可以回答您的问题。

【讨论】:

感谢您的回复 Val。我知道 execution_hint 可能会被覆盖,但我必须提醒您,查询在使用 global_ordinals_low_cardinality 时执行显着更好,所以我认为它不会被忽略。其次,我还想知道,为什么高基数字符串字段上的术语聚合可能比其长哈希对应项上的术语聚合性能好得多,后者甚至根本不需要全局序数。 .? 如果你看我的第二点,我说这个提示只会被你的 long 字段忽略,它回答了你的第二个问题。如果您确实指定了提示,那么 ES 当然会盲目地考虑它(除非该字段不支持序数)。至于为什么global_ordinals_low_cardinality 的表现比同行好很多,this pull request 可能会有所启发。 我在这里得到了问题第二部分的答案:discuss.elastic.co/t/… 但是,我仍然不清楚为什么 global_ordinals_low_cardinality 即使在高基数字段上也能更好地工作。 感谢您的跟进。正如 jpountz 所说, global_ordinals_low_cardinality 是最快的执行模式,但会占用内存。也许你有足够的可用内存,所以它最终不会产生任何影响,你也不会注意到任何事情。 也许我确实有足够的内存,但是我希望看到堆使用量增加,但我没有。但是,我不能很有信心地说我彻底测试了最后一条语句,所以我会在下周进行一些测试,并进行相应的更新。

以上是关于术语聚合性能高基数的主要内容,如果未能解决你的问题,请参考以下文章

具有高基数的雪花性能调优列

Elasticsearch 术语或基数聚合 - 按不同值的数量排序

实现高并发内存池

行项目维和高基数

实现高并发内存池

基数排序的算法思想及性能分析