【问题标题】:how to optimize the aggregation query in elasticsearch如何优化elasticsearch中的聚合查询
【发布时间】:2016-10-04 07:30:59
【问题描述】:

现在我正在使用 ES 进行聚合。基本逻辑可以表示为

select count(*)
from 
(select key, count(*) from table where *** 

按具有 count(*) > c 的键分组 ) z 这里的过滤条件由最终用户指定,这意味着我不能做任何前期工作。 我已经使用桶选择器实现了逻辑。

但是在我的例子中,通常有几百万个不同的键,这意味着 ES 返回了几百万个桶,默认情况下按它们的 doc_count 排序。这是非常耗时的。不知道有没有什么策略可以加快查询速度,比如关闭排序。

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    如果我理解正确,您的查询会执行以下操作:

    1. key对所有条目进行分组
    2. 删除count <= c 所在的所有分组条目
    3. 计算所有剩余的分组条目

    那么SELECT key, count(*) 就没有用了,因为它再也不会被使用了。你可以简单地使用SELECT 1

    这个查询根本不需要排序。


    基本上有3种方法可以加速这个查询:

    1. 获取更多服务器!这种聚合可以很容易地由 ES 在多个节点上并行执行。

    2. 不要在需要时聚合数据,而是使用每天执行一次的后台任务。此后台任务将基本上创建与您在下面的STORE 2 中看到的相同的数据。当然,这样一来,您将始终需要交付旧数据,但它会加快速度!

    3. 预聚合您的数据!使用一些简单的 Key-Value Storage(或者甚至可能只是坚持使用 ES 进行此操作),然后执行以下操作:

      • 插入新文档时:获取其密钥,并增加数字。

      • 当一个文档被删除时:获取它的键,并减少计数器。

    那么你基本上有 2 个存储:1 个用于实际文档,1 个用于聚合数据,即

    STORE 1:
    [
      {id: 1, key: foo, ...},
      {id: 2, key: foo, ...},
      {id: 3, key: bar, ...},
      {id: 4, key: baz, ...}
    ]
    
    STORE 2:
    [
      {id: foo, counter: 2},
      {id: bar, counter: 1},
      {id: baz, counter: 1}
    ]
    

    这样您在从STORE 1 插入/删除文档时进行聚合。这在插入/删除时当然会更耗时,因为您每次都必须触摸 2 个数据存储。

    但是现在您可以简单地计算来自STORE 2 的条目来获得您的结果。这将大大提高此操作的查询性能。


    你看:这总是一个权衡。你必须决定你需要什么:

    1. 实时数据 + 高插入/删除性能 + 慢聚合

    2. 非实时数据+高插入/删除性能+快速聚合

    3. 实时数据 + 慢速插入/删除 + 快速聚合

    【讨论】:

    • 感谢您的回答。但是我忘了提到用户总是会在他们的查询中添加一些过滤条件。所以在聚合之前,我必须做一些过滤工作,这会使预聚合没有用处。还是非常感谢
    猜你喜欢
    • 1970-01-01
    • 2010-12-18
    • 2021-09-03
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多