全表扫描不是“会不会发生”的问题,而是“有没有主动拦住它”的问题;必须用EXPLAIN验证执行计划,type=ALL或rows接近总行数即为全表扫描,常见诱因包括索引列用函数、左模糊LIKE、OR多非索引字段、联合索引顺序错误及大偏移分页。

直接说结论:全表扫描不是“会不会发生”的问题,而是“有没有主动拦住它”的问题。只要 WHERE 条件没命中索引、或 offset 过大、或 SQL 写法踩坑,MySQL 就会默默扫完整张表——哪怕你只想要第 1 条数据。
EXPLAIN 是唯一能确认是否全表扫描的工具
别猜,也别信“我加了索引就肯定走索引”。必须用 EXPLAIN 看执行计划,重点关注两个字段:
-
type字段为ALL:铁定全表扫描 -
rows值接近表总行数(比如表有 80 万行,rows显示 795231):基本等于在扫表
PHP 中最简验证方式:
$stmt = $pdo->query("EXPLAIN SELECT * FROM users WHERE username = 'test'");
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
注意:不要在生产环境高频执行 EXPLAIN,它本身不锁表但会触发查询优化器分析,高并发下也有开销。
WHERE 条件写法让索引直接失效
即使字段上有索引,下面这些写法也会导致 MySQL 放弃使用索引,强制全表扫描:
- 对索引列用函数:
WHERE YEAR(create_time) = 2023→ 改成WHERE create_time >= '2023-01-01' AND create_time - LIKE 左模糊:
WHERE name LIKE '%abc'或WHERE name LIKE '%abc%'→ 无法走 B+ 树索引,考虑全文索引或前置冗余字段 - 在等号左边做运算:
WHERE id + 1 = 100→ 改成WHERE id = 99 - 用
!=、OR、IS NULL且无对应索引覆盖 → 比如WHERE status != 1,除非该列区分度极高且走了索引覆盖,否则大概率扫表
特别提醒:IN 不是绝对安全。如果 IN 的值太多(比如几百个),优化器可能放弃索引而选全表扫描;连续数值优先用 BETWEEN。
ThinkPHP 分页绕过导致隐性全表扫描
ThinkPHP 的 paginate() 默认不校验页码上限,攻击者传 page=999999,框架会生成类似 LIMIT 9999980, 20 的语句——MySQL 必须先跳过前 999 万行,哪怕有索引,B+ 树也要从根逐层遍历到叶子,I/O 和 CPU 双爆。
必须做的三件事:
- 手动截断页码:
$page = input('page/d', 1); if ($page > 1000) abort(400, 'page too deep'); - 禁用裸
offset:永远不要把input('offset')直接喂给offset();改用min(max(0, intval($offset)), 50000)限死范围 - 高频分页接口加缓存:
cache('page_user_list_' . md5($key), $data, 300),并配合游标分页(如WHERE id > ? ORDER BY id LIMIT 20)替代深度 offset
TP6.3+ 支持预估总数传入:paginate(['total' => min($estimated, 500000)]),避免慢 COUNT(*) 拖垮整个请求。
联合索引顺序错,等于没建
联合索引 (a, b, c) 只能高效支持以下条件:
WHERE a = ?WHERE a = ? AND b = ?WHERE a = ? AND b = ? AND c = ?WHERE a = ? AND b BETWEEN ? AND ? ORDER BY c
但对 WHERE b = ? 或 WHERE b = ? AND c = ? 完全无效——这就是“最左前缀原则”被违反。常见翻车场景:
订单表查 user_id = 123 AND status = 2,却建了索引 (status, user_id) → 实际执行时仍全表扫描。
正确做法是按查询频率和选择性排序:高频且高区分度的字段放最左。例如用户登录查 username,几乎总是单条件,那就单独建索引;而订单列表常按 user_id + created_at 查,则建 (user_id, created_at)。
最容易被忽略的一点:索引不是建了就完事。表数据量增长后,原本高效的索引可能因数据分布变化而退化;EXPLAIN 要定期看,特别是上线新功能或批量导入数据后。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











