写出高效SQL的3个肌肉记忆:从新手到老手的习惯养成
关键词SQL优化肌肉记忆WHERE条件JOIN分页批量操作大家好我是小耶。前面两周讲了各种慢查询案例今天不展开新知识点只总结三个最实用的“肌肉记忆”。不是我编的是我踩坑踩出来的。1 肌肉记忆一WHERE条件里的字段绝不“加工”核心索引列保持原样不做任何变换。错误写法正确写法原理WHERE DATE(order_date) 2026-05-01WHERE order_date 2026-05-01 AND order_date 2026-05-02函数让索引失效改范围查询WHERE price 10 100WHERE price 90运算移到右边WHERE phone 13812345678phone是varcharWHERE phone 13812345678类型不匹配触发隐式转换养成习惯写完WHERE条件后检查等号左边有没有函数、运算或类型不一致。2 肌肉记忆二存在性检查用EXISTS别滥用IN或JOINDISTINCT很多新人看到“查A表中存在于B表的数据”第一反应是IN或JOIN。但在MySQL中EXISTS通常是最优解-- ✅ 推荐写法存在性检查 SELECT * FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id u.user_id); -- ❌ 可能有临时表开销的写法 SELECT DISTINCT u.* FROM users u JOIN orders o ON u.user_id o.user_id;为什么EXISTS一旦在内层找到匹配就立即停止扫描且不需要生成去重临时表。JOIN可能产生重复行必须加DISTINCT而DISTINCT在大表上可能创建磁盘临时表反而更慢。什么时候用JOIN需要同时返回两张表的字段时。单纯判断存在无脑用EXISTS。3 肌肉记忆三分页和批量操作必须“刹车”3.1 分页不用LIMIT M,N深分页-- ❌ 深分页扫描100万行再取10行 SELECT * FROM orders ORDER BY id LIMIT 1000000, 10; -- ✅ 游标分页记录上一页最后id SELECT * FROM orders WHERE id 上一页最大id ORDER BY id LIMIT 10;3.2 批量删除/更新一次不超过1000行-- ❌ 一次性删除几百万行长事务锁表 DELETE FROM logs WHERE created_at 2025-01-01; -- ✅ 分批删除循环执行 DELETE FROM logs WHERE created_at 2025-01-01 LIMIT 1000;3.3 修改数据前先SELECT验证影响行数BEGIN; SELECT COUNT(*) FROM orders WHERE status 测试; -- 确认行数正确再执行 DELETE FROM orders WHERE status 测试; COMMIT;4 总结三个习惯能让你避免多少坑不对WHERE字段“加工”避免90%的索引失效问题。存在性检查用EXISTS避免不必要的JOIN DISTINCT临时表开销。分页批量加“刹车”避免深分页、长事务、锁表事故。这些都不是高深理论而是每次写SQL时多看一眼就能做到的事。养成肌肉记忆你的代码会更稳加班会更少。小耶在手SQL 不愁。还有什么想了解的欢迎留言小耶一定知无不言言无不尽……我们下次见~参考文献[1] MySQL官方文档Optimization with EXISTS[2] 《高性能MySQL》第4版第4章“查询优化”[3] 阿里云数据库分页查询优化实践