首页 > 解决方案 > Postgresql:序列扫描而不是索引扫描

问题描述

我有下表:

create table if not exists inventory
(
    expired_at timestamp(0),
    -- ...
);

create index if not exists inventory_expired_at_index
    on inventory (expired_at);

但是,当我运行以下查询时:

EXPLAIN UPDATE "inventory" SET "status" = 'expired' WHERE "expired_at" < '2020-12-08 12:05:00';

我得到下一个执行计划:

Update on inventory  (cost=0.00..4.09 rows=2 width=126)
  ->  Seq Scan on inventory  (cost=0.00..4.09 rows=2 width=126)
        Filter: (expired_at < '2020-12-08 12:05:00'::timestamp without time zone)

大数据集也是如此:

EXPLAIN SELECT * FROM "inventory"  WHERE "expired_at" < '2020-12-08 12:05:00';
-[ RECORD 1 ]---------------------------------------------------------------------------
QUERY PLAN | Seq Scan on inventory  (cost=0.00..58616.63 rows=1281058 width=71)
-[ RECORD 2 ]---------------------------------------------------------------------------
QUERY PLAN |   Filter: (expired_at < '2020-12-08 12:05:00'::timestamp without time zone)

问题是:为什么Index Scan不但是Seq Scan

标签: sqlpostgresqlindexingsql-execution-planexplain

解决方案


这是一个有点长的评论。

简短的回答是您在表格中有两行,所以它没有任何区别。

更长的答案是您正在使用update,因此无论如何都必须检索数据行。使用索引需要加载索引和数据行,然后从索引间接到数据行。这有点复杂。而且有两排,根本不值得努力。

索引的强大之处在于处理大量数据,而不是少量数据。

回答这个大问题:数据库优化器不需要使用索引。他们使用某种措施(通常是基于成本的优化)来确定索引是否合适。在您的较大示例中,优化器已确定索引不合适。如果统计信息与基础数据不同步,则可能会发生这种情况。


推荐阅读