索引与查询计划:从 EXPLAIN 到执行优化
0. 元信息
- 主题路径:
docs/topics/db-and-sql/subtopics/index-and-query-plan/README.md - 主分类:计算机基础
- 辅助分类:Web 与后端
- 适合对象:完成父主题前置阶段的开发者
- 建议周期:1~3 周,每周 8~12 小时
- 前置知识:relational-model-and-sql
- 最终目标:能用 EXPLAIN ANALYZE 与 buffers 找到估算偏差并验证索引改动
1. 学习路线
数据分布 → 统计信息 → 候选访问路径 → 成本估算 → 执行计划
2. 阶段周数分配
本子主题按实验推进,不固定周数。每完成一个概念就留下 SQL、输入数据、输出和解释。
3. 九阶段表(精简)
| 阶段 | 核心知识 | 实践产出 | 学会标准 |
|---|---|---|---|
| 1. 建模 | heap、page、B+Tree、Hash、GiST、statistics、planner、executor | 概念图与最小 schema | 能说清每个概念解决什么问题 |
| 2. 实验 | PostgreSQL 行为、错误与边界 | 可重跑 SQL | 能预测正常和异常结果 |
| 3. 对照 | MySQL/SQLite 差异 | 差异表 | 能区分标准语义和实现行为 |
| 4. 工程 | 版本、数据规模、可观测输出 | 技术报告 | 能用证据解释选择 |
4. 第一周任务
精简版不固定 Day 1~7。执行约定是 PostgreSQL 16+、psql -v ON_ERROR_STOP=1、脚本可在空库重复运行。
5. 阶段通用验收
以 §3 的可观察标准和 §9.4 题目为验收。
6. 最终验收
独立完成一份最小实验、三组数据、一份解释和一次 PostgreSQL/MySQL 行为对照。
7. 综合项目
并入父主题“小型电商数据库”,本子主题负责 查询计划调优 的设计、实验与报告。
本主题贡献
- 在父主题
db-and-sql的综合项目「小型电商数据库」中,本主题(索引与查询计划)负责 查询计划调优:用 B+Tree / Hash / GiST、planner 与 executor 把上层 SQL 变成可解释的执行计划,并通过EXPLAIN (ANALYZE, BUFFERS)锁定代价热点与统计偏差。 - 把 §1 路线「数据分布 → 统计信息 → 候选访问路径 → 成本估算 → 执行计划」落到 3 条真实查询(订单按时段聚合、商品按分类筛选、库存按 SKU 列表
IN)上:每条查询给改前 / 改后两份 EXPLAIN;用BUFFERS量化 shared hit / read、local hit、temp written;用ANALYZE后 estimated vs actual rows 找出统计偏差并修正(重新ANALYZE、CREATE STATISTICS、扩大 sample)。 - 与 db-and-sql 其它子主题对接:B+Tree 复合索引列顺序遵从 relational-model-and-sql 给出的查询前缀;为 transaction-and-isolation 的 WHERE 条件提供索引建议,并测出 RR 下走 Index Only Scan 还是 Heap Fetch(heap fetches 不等于 IO miss)。
交付物清单:
plans/before.sql / plans/after.sql:3 条核心查询改前 / 改后 EXPLAIN ANALYZE 全量文本(含 cost / rows / time / Buffers),落到 git 仓库可复现到 commit hash;plans/composite_index.md:≥ 5 条复合索引设计,附「等值列放最左、范围列在后」的 EXPLAIN 证据与前缀规律演示;plans/stats_skew.md:制造数据倾斜后 estimated vs actual rows ≥ 10× 偏差的 3 条 SQL,证明重新 ANALYZE 与扩展统计 (CREATE STATISTICS) 的效果;plans/pg_vs_mysql_explain.md:PostgreSQLEXPLAIN (ANALYZE, BUFFERS)与 MySQLEXPLAIN FORMAT=TREE / JSON在 hash join / nested loop / index condition pushdown / BKA 上的差异。
验收标准:
- 3 条核心查询中至少 2 条加索引后 P95 延迟降幅 ≥ 50%,且结果集行数未变;
- 至少 1 条 estimated / actual rows 比 ≥ 5×,并给出修正(重新 ANALYZE / 增加统计 / 改写 SQL)的证据;
- 全部 EXPLAIN 输出落到 git 仓库并打
git tag,可复现到该 commit。
8. 推荐资料
见 §9.3。先用 PostgreSQL 官方文档和课程实验,书用于补理论。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
索引减少扫描范围,成本优化器选择访问路径。真实系统还要处理数据规模、失败和并发。我们用 PostgreSQL 实验观察语义,再用 MySQL 核对实现差异。
9.2 概念地图
flowchart LR
A[需求与数据] --> B[关系与约束]
B --> C[SQL]
C --> D[Planner / Transaction]
I[Index / Statistics] --> D
D --> E[执行与并发]
E --> F[结果 / 延迟 / 锁等待]
F --> G[验证与修改]
G --> C
核心概念:heap、page、B+Tree、Hash、GiST、statistics、planner、executor。图中从业务不变量出发,经 SQL、计划或事务到可观察结果,再用相同数据验证修改。
9.3 基础知识讲解
9.3.1 经典论文
| 资料 | 贡献 | 读法 |
|---|---|---|
| Codd, A Relational Model of Data for Large Shared Data Banks | 关系模型与 data independence | 读定义与例子 |
| Selinger et al., Access Path Selection in a Relational DBMS | 成本优化器 | 对照 EXPLAIN |
| Gray et al., Granularity of Locks and Degrees of Consistency | 锁与一致性 | 画锁兼容和事务 schedule |
9.3.2 经典书籍
| 书 | 侧重 | 用法 |
|---|---|---|
| Silberschatz, Korth & Sudarshan, Database System Concepts | 全景教材 | 读本子主题对应章 |
| C. J. Date, Database Design and Relational Theory | 关系理论 | 核对键、依赖与范式 |
| Joe Celko, SQL for Smarties | 高级 SQL | 复做集合式查询 |
9.3.3 优秀博客与文档
| 资料 | 特点 | 用法 |
|---|---|---|
| PostgreSQL Documentation | 权威行为说明 | 查目标版本 |
| Use The Index, Luke | Markus Winand 的索引与 SQL 案例 | 复现实验 |
| MySQL Reference Manual | MySQL/InnoDB 对照 | 核对方言和默认值 |
9.3.4 核心人物
| 人物 | 影响 | 材料 |
|---|---|---|
| Edgar F. Codd | 关系模型 | 1970 论文 |
| C. J. Date | 关系理论与教学 | 关系理论著作 |
| Andy Pavlo | 数据库系统教学与研究 | CMU 15-445 课程 |
9.3.5 开发与学习方法
| 方法 | 动作 | 何时用 |
|---|---|---|
| Query-first | 先写期望结果和业务不变量 | 正确性设计 |
| Single-variable experiment | 每次只改一处 SQL、索引或事务设置 | 因果验证 |
| Differential test | PostgreSQL 与 MySQL 对跑 | 识别标准与实现差异 |
课程补充:CMU 15-445 适合数据库实现,Berkeley CS186 适合系统课程与实验。Andy Pavlo 的课堂讲解用于连接论文、实现与计划输出。
9.4 经典问题与经典案例
| 问题 | 为什么重要 | 最简答案 |
|---|---|---|
| 为什么有索引仍 Seq Scan | 防止概念或工程误判 | 低选择性或小表时顺扫更便宜 |
| 复合索引列顺序怎么定 | 防止概念或工程误判 | 看等值、范围、排序与查询前缀 |
| estimated rows 偏差为何危险 | 防止概念或工程误判 | 会导致错误 join order 和算法 |
| EXPLAIN ANALYZE 做什么 | 防止概念或工程误判 | 真实执行并报告 actual time/rows |
| 覆盖索引一定不回表吗 | 防止概念或工程误判 | 可见性与实现条件仍可能访问 heap |
| GiST 适合什么 | 防止概念或工程误判 | 多维、范围、几何等可扩展操作类 |
9.5 学习难点
概念难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 抽象语义与产品实现 | 教材定义和默认行为容易混在一起 | 先写标准概念,再查目标版本文档 |
| 多个概念同时影响结果 | 单看 SQL 文本不够 | 画数据、计划或事务时间线 |
| NULL、重复或并发边界 | 正常样例会隐藏问题 | 强制加入边界数据和双会话实验 |
思维难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 集合与状态推理 | 容易按应用循环想问题 | 先写结果关系或状态不变量 |
| 从相关性到因果 | 改动后变快不代表改动有效 | 固定数据与环境,每次只改一项 |
| 正确性与性能并看 | 快结果可能是错结果 | 先断言结果,再比较计划和耗时 |
工程难点
| 难点 | 为什么会卡 | 突破路径 |
|---|---|---|
| 数据形状不真实 | 小样本计划没有代表性 | 测规模、选择性、倾斜和 NULL |
| 版本差异 | 默认值与语法会变 | 保存 SELECT version() 和引用日期 |
| 实验不可重跑 | 手工操作丢步骤 | DDL、seed、query、cleanup 全写脚本 |
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 主流版本 | 发布组织 | 状态 | 许可证 / 可访问性 |
|---|---|---|---|---|
| PostgreSQL | 16~18 | PGDG | 活跃 | PostgreSQL License;文档公开 |
| MySQL | 8.4 LTS / 9.x | Oracle | 活跃 | GPLv2 Community / 商业版 |
| SQLite | 3.x | SQLite Consortium | 活跃 | Public Domain |
| Oracle Database | 19c / 23ai | Oracle | 活跃 | 商业许可 |
| SQL Server | 2022 / 2025 | Microsoft | 活跃 | 商业/Developer |
| SQL | ISO/IEC 9075 | ISO/IEC JTC 1/SC 32 | 持续修订 | 正文通常收费 |
9.6.2 Scope
本子主题处理 查询计划调优。SQL 标准描述通用语义,产品文档描述 planner、storage、locking 等实现。不要把 PostgreSQL 扩展当成所有数据库的共同保证。
9.6.3 Structure
必须掌握的接口:DDL/DML、约束、SELECT/JOIN、事务控制、EXPLAIN (ANALYZE, BUFFERS)、system catalog 与统计视图。具体重点是:heap、page、B+Tree、Hash、GiST、statistics、planner、executor。
9.6.4 Ecosystem
PostgreSQL 是主实验环境。MySQL 用于 InnoDB 和 optimizer 对照。SQLite 适合单文件实验。Oracle 与 SQL Server 用来了解企业产品的方言、执行计划和并发差异。JDBC、ODBC、DB-API 是常见客户端接口。
9.6.5 Depth Tiers
| 层级 | 能力 | 可观察标准 |
|---|---|---|
| L0 | 知道存在 | 能说出核心名词 |
| L1 | 看得懂示例 | 能读 SQL、计划或事务脚本 |
| L2 | 能正确调用 | 能完成正常与边界实验 |
| L3 | 能解释与排错 | 能用结果、计划、锁或日志解释问题并验证修改 |
| L4 | 能设计与扩展 | 能修改优化器、存储或并发控制实现 |
本计划要求达到 L3。
9.6.6 Source
- PostgreSQL 官方文档:引用快照 2026-07-30。
- MySQL Reference Manual:引用快照 2026-07-30。
- ISO SQL 标准条目:引用快照 2026-07-30。
10. 常见误区
- 用单个正常样例证明理解;
- 混淆逻辑结果与物理执行顺序;
- 忽略 NULL 与三值逻辑;
- 把数据库默认行为当业务规范;
- 不保存版本、DDL 和种子数据;
- 看到索引就断言查询会更快;
- 只看平均耗时,不看计划和数据分布;
- 在生产直接试破坏性 SQL;
- 长事务里做网络调用;
- 跨数据库迁移时只检查语法;
- 用 ORM 隐藏生成 SQL 后不再检查;
- 修改后不重跑相同正确性断言。
11. 所有知识点分类(统一规则)
- 编程语言
- 数据结构与算法
- 计算机基础
- 工程技术
- Web 与后端
- 前端与客户端
- 数据与人工智能
- 项目与职业能力
- 安全与可靠性
本计划归属:计算机基础 主 + Web 与后端 辅。