【问题标题】:Postgresql: Seq Scan instead of Index ScanPostgresql:序列扫描而不是索引扫描
【发布时间】:2021-03-19 18:29:28
【问题描述】:

我有下表:

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

【问题讨论】:

  • 显然该表只包含两行。
  • @a_horse_with_no_name,添加大数据集示例
  • 仍然缺少重要信息:更新的行数。我们需要EXPLAIN (ANALYZE, BUFFERS) 输出。 (但请注意:ANALYZE 会执行该语句并修改行。在您回滚的事务中执行此操作。)

标签: sql postgresql indexing sql-execution-plan explain


【解决方案1】:

评论有点长。

简短的回答是表格中有两行,所以没有区别。

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

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

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

【讨论】:

  • 添加大数据集示例
猜你喜欢
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 2021-07-13
相关资源
最近更新 更多