00 / SCHEMA课堂库
先认识病人
全部题目跑在同一个脱敏副本上。行数是所有诊断的参照系。
students 12,000 行 (id, name, major, class_id, phone) enrollments 1,204,880 行 (id, student_id, course_id, term, score) courses 800 行 (id, title, teacher, credit) crawl_events 2,318,442 行 (id, student_id, url, title, created_at)
01 / DRILLS八条慢 SQL
从 ★ 全班必做,到 ★★★ 抢答
每题先读 SQL 与症状,走完三步再展开答案对照。
D1 · ★等值无索引ALL
SELECT * FROM students WHERE major = '大数据管理与应用';
type 是什么?rows 多少?怎么开方?
展开答案
判决:ALL · 12,000 行 · 0.94 s。处方:
CREATE INDEX idx_major ON students (major)。验证:ref · 214 行 · 0.01 s。原理:等值条件是索引最舒服的姿势——热身题,让学生把口令说顺。D2 · ★★不及格名单ALL
SELECT name, term, score FROM enrollments WHERE score < 60;
type 是什么?rows 多少?怎么开方?
展开答案
判决:ALL · 1,204,880 行 · 1.83 s。处方:
CREATE INDEX idx_score ON enrollments (score)。验证:range · 81,920 行 · 0.42 s。提醒:8 万次回表仍是大头——进阶方案是覆盖索引 (term, score),留给抢答。D3 · ★★复合条件只沾一半光ref 偏慢
-- 已有索引:idx_student(student_id) SELECT course_id, score FROM enrollments WHERE student_id = 42 AND term = '2026-秋';
索引已经命中了吗?还有多少优化空间?
展开答案
判决:ref · 244 行(命中 student_id 后,回表再过滤 term)· 0.11 s。处方:
CREATE INDEX idx_stu_term ON enrollments (student_id, term)。验证:ref · 37 行 · 0.01 s。原理:两个等值列都进索引,过滤在索引层完成。D4 · ★★★前导通配符姿势病
-- 即便 idx_title 存在 SELECT id, title FROM courses WHERE title LIKE '%数据库%';
索引为什么帮不上忙?
展开答案
判决:ALL · 800 行——前导 % 让 B+ 树无法定位起点,有索引也用不上。处方:业务上改成前缀匹配
LIKE '数据库%',或上全文索引。教学点:表小不慢,但姿势是错的——考试只考姿势,生产才会考规模。D5 · ★★★类型穿错了衣服隐式转换
-- phone 是 VARCHAR(20) SELECT * FROM students WHERE phone = 13812345678;
列上明明有索引,为什么 key 是 NULL?
展开答案
判决:ALL · 12,000 行 · 0.92 s——字符串列拿数字查,MySQL 隐式转换,索引失效。处方:给值加上引号
WHERE phone = '13812345678'。验证:const · 1 行 · 0.00 s。一句话:给列穿对类型的外衣,索引才认。D6 · ★★本月的采集量ALL
SELECT COUNT(*) FROM crawl_events WHERE created_at >= '2026-11-01';
type 是什么?rows 多少?怎么开方?
展开答案
判决:ALL · 2,318,442 行 · 2.1 s。处方:
CREATE INDEX idx_created ON crawl_events (created_at)。验证:range · 96,113 行 · 0.18 s。原理:时间列是报表查询最常出现的位置,值得单独一条索引。D7 · ★★★排行榜的代价filesort
SELECT student_id, score FROM enrollments ORDER BY score DESC LIMIT 10;
没有 WHERE,为什么还是 1.9 秒?
展开答案
判决:ALL · 1,204,880 行 · Extra: Using filesort · 1.9 s——全表捞出来再排一遍。处方:
CREATE INDEX idx_score2 ON enrollments (score)。验证:index · 索引天然有序,LIMIT 10 只摸 10 行 · 0.00 s。原理:ORDER BY 也能吃索引——全表变 10 行。D8 · ★★★外键没索引(最像生产事故)38 s
-- 故意删掉了 enrollments.student_id 上的索引 SELECT s.name, e.score FROM students s JOIN enrollments e ON e.student_id = s.id WHERE s.class_id = 3;
为什么这条要跑 38 秒?
展开答案
判决:s 侧 ref 48 行,e 侧对每一行都全表扫——48 × 1,204,880 · 38 s。处方:
CREATE INDEX idx_e_student ON enrollments (student_id)。验证:0.02 s,提速近两千倍。原理:外键列没索引,JOIN 就是连环车祸。教学点:最接近真实生产事故的一题——建表评审时第一个查它。02 / HOWTO怎么用这八题
分组急诊赛的题库
抽题
★ 两题全班必做打底;★★、★★★ 按组抽签——抽到 D8 的组又悲又喜。
限时 20 分钟
走完三步急诊:定位 → 读片 → 开方。处方与前后耗时写进对比卡。
上墙
各组提速倍数实时上墙——大屏再一次当排行榜用。
评委抽问
随机抽一组问「为什么」;答不出,提速倍数减半计分。没有验证截图的处方,直接零分。
| 评分项 | 权重 | 怎么量 |
|---|---|---|
| 提速倍数 | 60 | 前后耗时之比,最高计 1000 倍封顶 |
| 讲得清程度 | 40 | 抽问「为什么」:type / rows / Extra 说对几条 |
| 验证截图 | 一票否决 | 没有前后对比的处方按玄学处理,不得分 |
「练习集的答案不在折叠里,在 EXPLAIN 里。」
—— 每一条答案都要亲手跑出来才算数;跑出来的数字,可能和折叠里的差一点——说出为什么,比数字本身更值钱。