我的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,
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进行了提取和重新排序。
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_time desc索引来获取最新的值,速度大约快20倍。
发布于 2018-08-25 03:30:08
因为您的查询不能是流水线的。
在可以流水线化的查询中,不需要完成上一个运算符的结果就可以开始处理下一个运算符。
在您的例子中,操作符"Index Only Scan“必须完成,然后才能执行下一个操作符"Sort”。
无法对查询进行流水线处理,因为没有包含所有查询列的唯一约束。
然而,就性能而言,它几乎无关紧要。对几行进行排序(可能只有1行?)不需要对数据库引擎做任何工作。
也许您应该尝试将unique约束添加到表中,看看行为是否发生了变化。尝试添加以下约束:
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);如果不能添加,那么not unique和PostgreSQL中的列组合考虑需要排序的多个行是正确的。
如果您可以添加它,那么就获得新的执行计划。
https://stackoverflow.com/questions/52010600
复制相似问题