1.应尽量避免在where子句中使用!=或<>操作符
2.应尽量避免在where子句中使用or来连接条件
如:select Id from t where num=10 or num=20
可以这样查询
Select id from t where num=10
Union all
Select id from t where num=20
3.in 和not in 也要慎用,否则会导致全表扫描
如:select id from t where num in(1,2,3)
对于连续的数值,能用between就不要用in了
如:select id from t where num between 1 and 3
4.下面的查询也将导致全表扫描
如:select id from t where name like ‘%abc%’
若提高效率,可以考虑全文检索
5.如果在where子句中使用参数,也会导致全表扫描。因为sql只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时,它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
Select id from t where num=@num
可以改为强制查询使用索引:
Select id from t with(index(索引名)) where num=@num
6.应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用而进行全表扫描。
如:select if from t where num/2=100
应改为:select id from t where num=100*2
7.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:select id from t where substring(name,1,3)=’abc’ ----name以abc开头的id
Select id from t where datadiff(day,createdate.’2005-11-30’)=0----‘2005-11-30’生成的id
应改为:
Select id from t where name like ‘abc%’
Select id from t where createdate>=’2005-11-30’ and createdate<’2005-12-1’
8.不要在where子句中的”=”左边进行函数,算术运算或其他表达式运算,否则系统将可能无法正确使用索引
9.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引不会被使用,并且应尽可能的让字段顺序与索引顺序相一致
10. 不要写一些没有意义的查询,如需要生成一个空表结构:
Create table #t(…)
11. 很多时候用exist代替in是一个好的选择
如: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 )
- 与临时表一样,游标并不是不可使用。对小型数据集使用FAST_FORWARD游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好
- 在所有的存储过程和触发器的开始处设置SET NOCOUNT ON ,在结束时设置SET NOCOUNT OFF。无需在执行存储过程和触发器的每个语句后在客户端发送DONE_IN_PROC消息
- 尽量避免大事务操作,提高系统并发能力
- 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理