首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的多列仅索引扫描读取索引中的所有行,然后在PostgreSQL中只返回一行?

为什么我的多列仅索引扫描读取索引中的所有行,然后在PostgreSQL中只返回一行?
EN

Stack Overflow用户
提问于 2018-08-25 03:23:27
回答 1查看 41关注 0票数 2

我的Postgres数据库中有以下多列索引:

代码语言:javascript
复制
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
);

此查询成功地对该索引执行了仅索引扫描:

代码语言:javascript
复制
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进行了提取和重新排序。

代码语言:javascript
复制
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倍。

EN

回答 1

Stack Overflow用户

发布于 2018-08-25 03:30:08

因为您的查询不能是流水线的。

在可以流水线化的查询中,不需要完成上一个运算符的结果就可以开始处理下一个运算符。

在您的例子中,操作符"Index Only Scan“必须完成,然后才能执行下一个操作符"Sort”。

无法对查询进行流水线处理,因为没有包含所有查询列的唯一约束

然而,就性能而言,它几乎无关紧要。对几行进行排序(可能只有1行?)不需要对数据库引擎做任何工作。

也许您应该尝试将unique约束添加到表中,看看行为是否发生了变化。尝试添加以下约束:

代码语言:javascript
复制
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中的列组合考虑需要排序的多个行是正确的。

如果您可以添加它,那么就获得新的执行计划。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52010600

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档