现在我正在使用ES进行聚合。基本逻辑可以表示为
select count(*)
from
(select key, count(*) from table where ***
按键分组(*)> C )z 这里过滤条件由最终用户指定,这意味着我不能做任何前期工作。 我已经使用桶选择器实现了逻辑。
但是在我的情况下,通常有数百万个不同的密钥,这意味着ES返回了数百万个桶,默认情况下按doc_count排序。这非常耗时。我不知道是否有一些策略可以加速查询,例如关闭排序。
答案 0 :(得分:1)
如果我理解正确,您的查询会执行以下操作:
key
count <= c
然后SELECT key, count(*)
没用,因为它永远不会被再次使用。您只需使用SELECT 1
。
此查询根本不需要排序。
基本上有3种加速查询的方法:
获取更多服务器!在多个节点上,ES可以轻松地并行执行此聚合。
请勿在需要时聚合数据,而是使用每天执行一次的后台任务。此后台任务基本上会创建相同的数据,如下面STORE 2
中所示。当然,通过这种方式,您将始终必须提供旧数据,但这会加快速度!
预先聚合您的数据!使用一些简单的键值存储(或者甚至只是坚持使用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
中的条目以获得结果。这将大大提高此操作的查询性能。
你看:这总是一个权衡。你必须决定你需要什么:
实时数据+高插入/删除性能+慢速聚合
非实时数据+高插入/删除性能+快速聚合
实时数据+慢插入/删除+快速聚合