为什么我的多列索引只能扫描索引中的所有行,而只能在PostgreSQL中返回一行?
我的Postgres数据库中有以下多列索引:为什么我的多列索引只能扫描索引中的所有行,而只能在PostgreSQL中返回一行?,sql,postgresql,indexing,Sql,Postgresql,Indexing,我的Postgres数据库中有以下多列索引: create index activity_get_latest_idx on activity using btree ( type, space_id, navigable_block_id, collection_id, mentioned_user_id, mentioned_block_id, mentioned_property, top_level_block_id,
create index activity_get_latest_idx on activity using btree (
type,
space_id,
navigable_block_id,
collection_id,
mentioned_user_id,
mentioned_block_id,
mentioned_property,
top_level_block_id,
collection_row_id,
discussion_id,
invited_user_id,
collection_view_id,
collection_property_id,
permission_group_id,
end_time desc,
id -- index-only scan
);
此查询成功地对该索引执行仅索引扫描:
explain analyze
select id from activity
where type = 'block-edited'
and space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'
and navigable_block_id = '67dcd86c-f1ed-4708-9d32-4bb4bdb41ac7'
and collection_id is null
and mentioned_user_id is null
and mentioned_block_id is null
and mentioned_property is null
and top_level_block_id is null
and collection_row_id is null
and discussion_id is null
and invited_user_id is null
and collection_view_id is null
and collection_property_id is null
and permission_group_id is null
order by end_time desc
limit 1;
但是,当我explain analyze
这个查询时,似乎rows=891
被提取出来并用heapsort重新排序
Limit (cost=8.75..8.76 rows=1 width=24) (actual time=0.999..1.000 rows=1 loops=1)
-> Sort (cost=8.75..8.76 rows=1 width=24) (actual time=0.998..0.998 rows=1 loops=1)
Sort Key: end_time DESC
Sort Method: top-N heapsort Memory: 25kB
-> Index Only Scan using activity_get_latest_idx on activity (cost=0.69..8.74 rows=1 width=24) (actual time=0.032..0.755 rows=891 loops=1)
Index Cond: ((type = 'block-edited'::activity_type) AND (space_id = '6d702c09-8795-4185-abb3-dc6b3e8907dc'::uuid) AND (navigable_block_id = '67dcd86c-f1ed-4708-9d32-4bb4bdb41ac7'::uuid) AND (collection_id IS NULL) AND (mentioned_user_id IS NULL) AND (mentioned_block_id IS NULL) AND (mentioned_property IS NULL) AND (top_level_block_id IS NULL) AND (collection_row_id IS NULL) AND (discussion_id IS NULL) AND (invited_user_id IS NULL) AND (collection_view_id IS NULL) AND (collection_property_id IS NULL) AND (permission_group_id IS NULL))
Heap Fetches: 18
Planning time: 0.184 ms
Execution time: 1.028 ms
你知道为什么会这样吗?似乎Postgres应该能够使用
end\u time desc
索引来获取最新的值,大约快20倍。因为您的查询无法管道化
在可以管道化的查询中,无需完成前一个运算符的结果即可开始处理下一个运算符
在您的情况下,必须先完成操作员“仅索引扫描”,然后才能执行下一个操作员“排序”
查询无法管道化,因为没有唯一的约束,它限制了所有查询列
尽管如此,就性能而言,这并不重要。排序几行(可能只有1行?)不需要对数据库引擎进行任何操作
也许您应该尝试将唯一约束添加到表中,看看行为是否发生了变化。尝试添加以下约束:
alter table activity add constraint uq1_activity unique (
type, space_id, navigable_block_id, collection_id, mentioned_user_id,
mentioned_block_id, mentioned_property, top_level_block_id,
collection_row_id, discussion_id, invited_user_id,
collection_view_id, collection_property_id, permission_group_id);
如果您不能添加它,那么在不唯一和PostgreSQL中的列组合是正确的,考虑需要排序的多行。
如果可以添加,则获取新的执行计划。我不完全确定您指的是什么。索引中的每一列都受此查询的约束,并且索引按结束时间排序。。。您指的是哪种类型的唯一约束?
对于唯一约束而言,空值被认为是不相等的。
1.028 ms相当快,因此我不确定在这种情况下您是否会获得很多性能提升。它不是“堆排序”,而是“top-N堆排序”-有些不同。而且从一个或多个行中获取第一行非常高效。如果在执行查询之前清空表会怎么样?这是不是因为表被更新了很多?