1.插入数据的表或临时表,预先创建好表结构,能够加快执行速度
2.where 条件判断的字段以及连接查询的条件字段 都添加上索引 能够加快执行速度
3.尽量避免使用 like ,类似 like ‘XX%’ 或like ‘%XX’ 可以使用 left(varchar,length) == ‘XX’ 来替代,可以加快执行速度
4.循环改批量处理
1).应用代码端一记 for 循环再恶心点的每次打开关闭连接,跑个几分钟,数量大点几小时。请把你的每次for循环出来的结果放在一个datatable,list啥的,不要找到一条就往数据库写一条!
2).数据库中的游标也是差不多的道理,如果有可能不用游标循环一条一条处理,请尽量不要使用。如果自己认为必须用,也请问问别人是否可以有其他方式做批量!
3).如果没法避免一条一条的写入,那么在处理前显示开启一个事务 begin tran 在处理完成后 commit 这样也要比不开显示事务会快很多!凡事有利有弊,这种显示开启大事务要保证的整体的过程不会执行特别长的时间,如果执行的操作特别多而且时间长就是灾难了!
5.降低语句的复杂性
把一些能拆分出来的尽量拆分出来放入临时表或者表变量中,比如先把条件筛选性较强的几张表关联,然后把结果放入临时表,在用临时表和其他表关联。可以理解成我有10张表关联,我先拿5张表出来关联,然后把结果放入临时表,再跟另外5张表关联。这样这个查 询的复杂度由10张表的联合变成 5+6,这样降低了复杂语句复杂度。复杂视图也是如此,在视图和外层关联前,放入临时表,再跟外层关联。子查询也是如此,可以分离出来成为临时表的子查询,先分离出来。
6.避免重复读取
1).多个存储过程顺序执行,每个存储过程都需要读取同一聚合数据,那么就将它们整合成1个存储过程,对聚合数据只读取一次。
2).考虑聚合数据的常用性,考虑使用临时表进行处理,大量数据写入临时表时,一定要用 先create 再 insert 的方式,不要直接使用 select into 临时表的方式,否则就是灾难了!
7.为必要的字段创建索引
1).创建的索引列不可以带函数,不可以参与计算 类似:where productID/2 = @a ,不能有隐式转换。
2).尽量把 where 条件中的字段建成一个组合索引,并且包含要查询 select 中的字段。
8.只返回必要的数据
1).不要写SELECT * 的语句,而是选择你需要的字段。
2).当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
3).where 条件要尽量的多且保证高筛选性。
4).业务中很常见要返回大批量数据到前端,但是这些数据真的都是必要的么?前端是否可以加一些默认条件呢?
9.减少不必要的操作
1).杜绝不必要的表连接,多一个表链接代表多很大部分开销。
2).减少不必要的条件判断,很多时候前台传入为空值得时候 后台语句被写成XX=XX OR XX IS NULL OR XX LIKE OR ...OR ...OR 等。这是比较经典的问题了,请加入判断在拼入最后的条件!
3).你的语句需要去重复么? distinct 、union等操作
4).LEFT JOIN 和 inner join的区别,是否真的需要left join,否则选用inner join 来减少不必要的数据返回。
5).order by 你的语句是否需要排序?排序是否可以通过索引来降低性能消耗? 我见过竟然插入数据也带着order by的 !
10.尽量早的筛选
1).最经典的例子就是where 和 having的区别,看过语句执行顺序你应该已经明白了。能写在where 中不要放在having中。
2).使用临时表降低语句复杂性,要降低临时表的数据量,也就是要把有条件的表尽量关联并做成临时表。
3).前面提到的隐式转换,索引字段使用计算或函数,也会导致数据不能尽早筛选。
11.常用的写法误区(以下都是网上片面结论)
所有别人提到的方法到底有无效
- or 要用union all 代替 (or是很常规的一种写法,情况分很多种,一个表的两个条件用 a.a =X or a.a = XX ,一个表两个字段用 a.a =X or a.b = x,两个不同表字段用 a.a = X or b.a = X 这是网上说的union all代替的)
- 避免使用 in、not in (数据量小的时候不会有问题,如果数据量大可能影响性能,数据量大处理方式先把in 中的数据放入临时表)
- 事务操作过程要尽量小,能拆分的事务要拆分开来。(前文中提到的例子,有些情况循环写入下,显示开启一个大事务会有很大帮助)
- 使用with(nolock)查询语句不会阻塞 (一般情况下是这样,但是如果有架构修改或快照发布等使用with(nolock)也会阻塞)
- 用exists 代替 in (情况也很复杂不能一概而论)