查询的英文速查手册:3个致命坑点让SQL性能崩盘
官方文档翻烂了还是写不出高性能查询?别慌,这份查询的英文速查手册直接帮你避开90%的坑。
坑的现象:明明数据量不大,为什么SELECT * FROM users WHERE name = 'John'执行要5秒?监控显示数据库CPU飙红,应用接口超时报警此起彼伏。新手常以为是数据量问题,实则多半是查询写法埋雷。
根本原因:90%的性能问题源于索引失效和隐式类型转换。MySQL等主流数据库在特定条件下会放弃索引扫描,转而全表扫描。比如WHERE id = '123'(字符串比较数字列),数据库会对每行数据做类型转换,索引直接作废。更隐蔽的是WHERE DATE(created_at) = '2024-01-01',函数包裹列名导致索引失效,百万级数据下查询时间从毫秒级劣化到秒级。
正确写法对比: 错误写法(索引失效):
SELECT * FROM orders
WHERE DATE(created_at) = '2024-01-01'
AND amount > 100;
正确写法(保留索引):
SELECT * FROM orders
WHERE created_at >= '2024-01-01 00:00:00'
AND created_at < '2024-01-02 00:00:00'
AND amount > 100;
关键差异:避免对索引列使用函数,改用范围查询。时间范围查询必须用左闭右开,确保索引连续命中。
复现与修复代码:
用EXPLAIN验证执行计划,关注type字段:
ALL:全表扫描,必须优化index:全索引扫描,次优range:范围扫描,良好ref:索引查找,优秀const:常量查找,最佳
修复步骤:
- 执行
EXPLAIN SELECT ...查看执行计划 - 检查
key列是否为NULL(索引未命中) - 检查
rows列预估扫描行数是否过大 - 调整查询条件,移除索引列函数
- 添加复合索引(如
INDEX(created_at, amount))
规避建议:
- 永远不要对索引列做计算或函数操作
- 字符串比较数字列会导致隐式转换,确保类型一致
- 复合索引遵循最左前缀原则,高频过滤条件放前面
- 用
EXPLAIN而非猜测,数据说话 - 大表查询避免
SELECT *,只取需要的列
你在项目里踩过这个坑吗?评论区聊聊