SQL查询优化30条军规:让数据库性能提升10倍
今天整理了30条SQL查询优化原则,每一条都是实战经验总结。用好它们,数据库性能提升立竿见影。
1. 查询优化第一步:在WHERE和ORDER BY涉及的列上建立索引
避免全表扫描,这是最基本也是最重要的原则。
2. 避免在WHERE子句中对字段进行NULL值判断
-- ❌ 会放弃索引SELECT id FROM t WHERE num IS NULL-- ✅ 设置默认值0后这样查SELECT id FROM t WHERE num = 0
3. 避免使用 != 或 <> 操作符
这些操作符会导致引擎放弃使用索引。
4. 避免使用OR连接条件
-- ❌ 全表扫描SELECT id FROM t WHERE num = 10 OR num = 20-- ✅ 用UNION ALL替代SELECT id FROM t WHERE num = 10UNION ALLSELECT id FROM t WHERE num = 20-- ❌ 全表扫描SELECT id FROM t WHERE num IN(1,2,3)-- ✅ 连续值用BETWEENSELECT id FROM t WHERE num BETWEEN 1 AND 3
6. 避免前缀模糊查询
-- ❌ 全表扫描SELECT id FROM t WHERE name LIKE '%abc%'-- ✅ 考虑全文检索-- 或者改为前缀匹配SELECT id FROM t WHERE name LIKE 'abc%'
7. WHERE子句中使用参数会导致全表扫描
-- ❌ 编译时未知值,无法使用索引SELECT id FROM t WHERE num = @num-- ✅ 强制使用索引SELECT id FROM t WITH(INDEX(索引名)) WHERE num = @num-- ❌ 全表扫描SELECT id FROM t WHERE num/2 = 100-- ✅ 改为对常量操作SELECT id FROM t WHERE num = 100 * 2-- ❌ 函数操作导致全表扫描SELECT id FROM t WHERE SUBSTRING(name,1,3) = 'abc'SELECT id FROM t WHERE DATEDIFF(day, createdate, '2005-11-30') = 0-- ✅ 改写SELECT id FROM t WHERE name LIKE 'abc%'SELECT id FROM t WHERE createdate >= '2005-11-30' AND createdate < '2005-12-01'
10. 不要在“=”左边进行函数或运算
系统可能无法正确使用索引。
11. 复合索引必须使用第一个字段
字段顺序应与索引顺序一致,否则索引不会被使用。
12. 不要写无意义的查询
-- ❌ 消耗资源SELECT col1,col2 INTO #t FROM t WHERE 1=0-- ✅ 直接建表CREATE TABLE #t(...)-- ❌SELECT num FROM a WHERE num IN(SELECT num FROM b)-- ✅SELECT num FROM a WHERE EXISTS(SELECT 1 FROM b WHERE num = a.num)
14. 索引不是万能的
当列有大量重复数据时(如性别字段),索引基本无效。
15. 索引不是越多越好
索引提高SELECT效率,降低INSERT/UPDATE效率
一个表索引数最好不要超过6个
定期清理不常用的索引
16. 避免频繁更新聚集索引列
聚集索引列改变会导致整个表物理顺序调整,消耗巨大资源。
17. 尽量使用数字型字段
数字比较一次完成,字符串需要逐个字符比较。
18. 用varchar/nvarchar代替char/nchar
变长字段存储空间小,查询效率更高。
**19. 不要用 SELECT ***
-- ❌ 返回不需要的字段SELECT * FROM t-- ✅ 只取需要的字段SELECT id, name FROM t
20. 优先使用表变量代替临时表
但注意表变量索引有限(只有主键)。
21. 避免频繁创建删除临时表
消耗系统表资源。
22. 临时表适用场景
需要重复引用大型表数据集时使用临时表
一次性事件用导出表
23. 数据量大的情况用SELECT INTO
-- 大批量插入用SELECT INTO,减少日志SELECT * INTO #t FROM large_tableTRUNCATE TABLE #tDROP TABLE #t
25. 尽量避免使用游标
游标效率差,超过1万行数据就应考虑改写。
26. 先找基于集的解决方案
集合操作通常比游标更有效。
27. 小型数据集可用FAST_FORWARD游标
必须引用多个表时才考虑使用。
28. 存储过程设置SET NOCOUNT ON
CREATE PROC xxxASSET NOCOUNT ON-- 你的代码SET NOCOUNT OFF
减少客户端消息流量。
29. 避免大事务操作
大事务会锁定大量资源,影响并发能力。
30. 避免返回大数据量
数据量过大时,考虑分页或调整需求。
这30条原则核心就是一句话:让数据库能用上索引,减少全表扫描。
✅ 索引:建在WHERE/ORDER BY列
❌ 避免:NULL、!=、OR、IN、函数、左侧运算
✅ 推荐:EXISTS代替IN、数字型、varchar、指定字段
阅读原文:原文链接