我有一个表,其中包含几 TB 的事件数据,采用非常简单的(id、bucket_id、data、created_at)模式,并且有一个像这样的索引
create index index_events_on_created_at_and_bucket_id
on public.events (created_at desc, bucket_id asc);
现在我认为使用如下查询可以快速找到每个存储桶中最新事件的 id:
select max(created_at), bucket_id from events group by bucket_id;
解释输出:
HashAggregate (cost=170172168.62..170172178.41 rows=979 width=16)
Group Key: bucket_id
-> Index Only Scan using index_events_on_created_at_and_bucket_id on events (cost=0.70..156003994.34 rows=2833634856 width=16)
它似乎正在使用索引,但是进行索引扫描,而不是像我预期的那样仅仅获取头值。无论哪种方式,它都无法及时完成。我认为这是在查询中使用聚合函数的问题,但我不知道如何修复它。
created_at
是否有一个查询可以通过从该索引中获取每个存储桶来返回最新的(即索引中的第一个)时间戳?
更好的领先索引
bucket_id
您想要每个桶一行。带前导的 索引
bucket_id
会更有用。有关的:
bucket_id
由于( "rows=979" )中的不同值数量非常少,因此根据我建议的索引,此查询技术应该会为您提供更快的结果:它模拟“松散索引扫描”,只为每个不同的行选择“第一”行
bucket_id
- 正是您正在寻找的内容。请注意查询中的排序顺序如何与索引精确匹配。
如果表的可见性映射是最新的(即表已被足够清理),您将获得仅索引扫描。应该适用,因为您演示的慢速查询也进行了仅索引扫描。(尽管这是扫描整个索引,而不是仅扫描每个存储桶的前导条目)。有关的:
这假设感兴趣的两列都是
NOT NULL
。否则你必须做更多的事情。如果您还有
bucket
一个表,每个相关的一行bucket_id
,这甚至会更快一点:看:
卡在索引上
(created_at DESC, bucket_id ASC)
我们可以使用您评论中的附加元信息:
您可以增强上面的查询,但基于此的不同角度应该表现得更好:
当仅限于最近行的微小(?)部分时应该更快。Postgres 可以从索引中读取顶部行并将其提供给
DISTINCT ON
. 关于DISTINCT ON
: