sql - 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
?
解决方案
这是一个有点长的评论。
简短的回答是您在表格中有两行,所以它没有任何区别。
更长的答案是您正在使用update
,因此无论如何都必须检索数据行。使用索引需要加载索引和数据行,然后从索引间接到数据行。这有点复杂。而且有两排,根本不值得努力。
索引的强大之处在于处理大量数据,而不是少量数据。
回答这个大问题:数据库优化器不需要使用索引。他们使用某种措施(通常是基于成本的优化)来确定索引是否合适。在您的较大示例中,优化器已确定索引不合适。如果统计信息与基础数据不同步,则可能会发生这种情况。
推荐阅读
- .net - 在 asp.net 中将目标框架从 .net 框架更改为 .net 核心
- amazon-web-services - 如何替换正在使用 CF 模板部署的 lambda 函数中的字段
- javascript - 更新时 ComponentDidUpdate 不起作用
- javascript - 浏览器支持,同时包含 HTML
- java - 使用 maven-compiler-plugin 和 aspectj-maven-plugin 进行编译
- android - Flutter 插件:InAppPurchasePlugin.java 使用未经检查或不安全的操作
- mysql - 查询以计算前几行中出现的数字的计数
- c++ - 未来可以安全地传递给分离的线程吗?
- mocha.js - 使用 mocha、chai 和 supertest 进行身份验证时出现问题
- c++ - 如何找出在 DLL 中调用了哪些函数?