顺序扫描与索引扫描
了解什么时候顺序扫描已经足够,什么时候必须使用索引扫描,以及规划器如何做出决定
顺序扫描与索引扫描 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。
查找行的两种方式
数据库有两种读取行的基本策略:
- 顺序扫描 — 读取表的每个页面
- 索引扫描 — 遍历索引并获取匹配的行
顺序扫描适用的情况
如果无论如何都需要读取表中的大多数数据,那么扫描比读取索引并获取每个匹配行更便宜。大致来说:超过约 10–20% 的行 → 顺序扫描更优。
索引扫描更优的情况
对于选择性较高的查询(只涉及少量行),索引能够发挥作用:
EXPLAIN SELECT * FROM users WHERE id = 42;
-- Index Scan using users_pkey (cost=0.43..8.45 rows=1)
EXPLAIN SELECT * FROM users WHERE active;
-- Seq Scan on users (cost=0.00..15000.00 rows=950000)
-- (because most users are active)索引扫描与仅索引扫描
有时索引本身就包含您需要的所有列,因此不需要读取表。这就是仅索引扫描:
CREATE INDEX users_email_id_idx ON users(id) INCLUDE (email);
EXPLAIN SELECT email FROM users WHERE id = 42;
-- Index Only Scan using users_email_id_idx位图索引扫描
对于中等选择性的查询,PostgreSQL 可能会先为匹配的行建立位图,再按物理顺序获取这些行,这比随机输入/输出更快:
EXPLAIN SELECT * FROM orders WHERE status = 'pending';
-- Bitmap Heap Scan on orders
-- Recheck Cond: (status = 'pending')
-- -> Bitmap Index Scan on orders_status_idx规划器选择顺序扫描的原因
常见原因包括:
- 过滤列上没有索引
- 索引无法使用(列上使用了函数、包含 OR 子句或类型不匹配)
- 预计行数太多,使用索引不划算
- 统计信息已过期,规划器错误地判断了选择性
谨慎强制使用索引
您无法直接向 PostgreSQL 提供提示。可以改为:
- 运行 ANALYZE 以刷新统计信息
- 添加合适的索引
- 设置会话参数:使用
SET enable_seqscan = off;进行诊断(不要用于生产环境)
可使用索引的谓词
要让索引发挥作用,WHERE 条件必须能够直接使用索引,也就是直接比较索引列:
-- GOOD:
WHERE created_at >= '2024-01-01'
-- BAD (function on the column):
WHERE date_trunc('day', created_at) = '2024-01-01'
-- BAD (cast):
WHERE created_at::DATE = '2024-01-01'
-- FIX: add a functional index, or rewrite with range.复合索引的顺序
包含 (a, b) 的索引可以帮助仅查询 a 或同时查询 a AND b 的语句,但不能帮助仅查询 b 的语句。
索引大小很重要
包含热点键的窄 B 树索引可能完全保留在内存中,而宽索引则不一定。索引越小,速度越快。
验证计划
添加索引后,运行 EXPLAIN ANALYZE,确认规划器确实在使用它。如果没有使用,请继续查找原因。
回顾
选择顺序扫描还是索引扫描取决于选择性。
- 过滤条件选择性高 → 索引扫描
- 涉及表中大多数数据 → 顺序扫描
- 中间情况使用位图扫描
- 注意条件是否能够使用索引
快速检查
为什么 PostgreSQL 可能会选择顺序扫描,而不是使用已有索引?
常见问题解答
「顺序扫描与索引扫描」课时是免费的吗?
是的 — 「顺序扫描与索引扫描」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。
「顺序扫描与索引扫描」这节课中我会学到什么?
了解什么时候顺序扫描已经足够,什么时候必须使用索引扫描,以及规划器如何做出决定 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「顺序扫描与索引扫描」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Academy 课中编写并运行代码吗?
能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。