sql 语句优化

1.避免where子句使用 or 来链接条件

select * from orders where (customer_num=104 and order_num>100) or order_num = 1008sql

虽然在customer_num 和order_num 上建有索引,可是在上面的语句中优化器仍是使用顺序存取路径扫描整个表。由于这个语句要检索的是分离行的集合,改为并发

select * from orders where (customer_num=104 and order_num>100)
    union
select * from order where  order_num = 1008

2.避免相关子查询函数

一个 例的标签同时在主查询和where子句中的查询中出现,那么极可能当主查询中的列值改变以后,子查询必须从新查询一次,查询嵌套层次越多,效率越低,所以应当尽可能避免子查询。若是子查询不可避免那么要在子查询中过滤掉尽量个人行post

3.避免困难的正规表达式 like性能

matches 和 like 关键字支持通配符匹配,技术上叫正规表达式,但这种匹配特别耗费时间,例:优化

select * from customer where zipcode like '98_ _ _'
select id from customer where name like '%abc%';

即便在zipcode字段上创建了索引,在这种状况下也是采用扫描的方式。若是把语句改成设计

select * from customer where zipcode > '98000'

 在执行查询时就会利用索引来查询,显然会大大提升速度。code

4.使用临时表加速查询排序

把表的一个子集进行排序并建立临时表,有时能加速查询。有助于避免多重排序操做,并且在其余方面还有简化优化器的工做。例如:索引

select cus.name , rcvbles.balance , ,,,
from cust , rcvbles
where cus.customer_id = rcvlbes.customer_id
and rcvblls.balance>0
and cus.postcode > '98000'
order by cust.name

若是这个查询要被执行屡次而不止一次,可能把全部未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:

select cus.name , rcvbles.balance , ,,,
from cust , rcvbles
where cus.customer_id = rcvlbes.customer_id
and rcvblls.balance>0
order by cust.nameinto temp cust_with_balance

而后如下面的方式在临时表中查询:

select * from cust_with_balance
where poscode > '98000'

临时表中的行要比主表中和行少,并且物理顺序就是所要求的顺序,减小了磁盘i/o,因此查询工做量能够获得大幅减小。

 临时表建立后不会反映主表的修改。在主表中数据频繁修改的状况下,注意不要丢失数据  

5.考虑在where 及 order by 涉及的列上创建索引

6. 避免在 where 子句中对字段进行null 值判断,不然将致使引擎放弃使用索引而进行全表扫描,如

select id from t where num is null

能够在num 上设置默认值0,确保表中num列没有null值,而后这样查询:

select id from t where num = 0

7.避免在wher 子句中使用 != 或 <> 操做符,不然将致使引擎放弃索引进行全表扫描

8. 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

9.若是在where 子句中使用参数,也会致使全表扫描

select id from t where num=@num <mailto:num=@num>

可改成强制查询使用索引:

select id from t with(index(索引名)) where num=@num <mailto:num=@num>

由于sql只有在运行时都会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时它必须在编译时进行选择。然而,若是在编译时创建访问计划,变量的值学是未知的,于是没法做为索引选择的输入项。

10. 避免在where 子句中对字段进行表达式操做,这将致使引擎放弃索引

select id from t where num/2 = 100

select id from t where num = 100*2

11. 避免在where 子句中地字段进行函数操做,这将致使引擎放弃使用索引而进行全表扫描

如:

select id from t where substring(name,1,3) = 'abc'

select id from t where datediff(day,createdate,'2005-11-30')

select id from t where name like 'abc%'

select id from t where createdate >= '2005-11-30' and createdate < '2005-12-1'

12.不要在where 子句的 ‘=’ 左边进行函数,算术运算或其余形式运算,不然系统将可能没法正确使用索引

13.使用数字型字段

若只含数据值的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。这是由于引擎在处理查询和链接时会逐个比较字符中每个字符,而对于数字型而言只须要比较一次就够了。

14.尽量的使用 varchar/nvarchar 代替 char/nchar

由于首先变长字段存储空间小,可节省存储空间,其次对于查询来讲,在一个相对较小的字段内搜索效率显然要高些。

15.任何地方都不要使用select * from t, 用具体的字段列表代替 ‘*’ ,不要返回用不到的任何字段

16.用表变量代替临时表

若是表变量包含大量数据,请注意索引很是有限(只有主键索引)

17.避免频繁建立和删除临时表,以减小系统资源的消耗

18. 临时表并非不可以使用,适当地使用它们可使某些例程理有效,例如,当须要重复引用大型表或经常使用表中的某个数据集时,
可是,对于一次性事件,最好使用导出表

19.在临时表时,若是一次性插入数据量很大,那么可使用 select into 代替 create table ,避免形成大量 log,以提升速度;
若是数据量不大,为了缓和系统表的资源,应先 create table ,而后 insert

20.若是使用到了临时表,在存储过程最后务必将全部的临时表显示删除,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定

21.尽可能避免使用游标,由于游标的效率较差,若是游标操做的数据超过1万行,那么就应该考虑改写

22.在全部的存储过程和触发器的开始处设置 set nocount no ,在结束时设置 set nocount off,无需在执行存储过程和触发器的每一个语句后向客户发送 done_in_proc 消息

23.尽可能避免大事务操做,提升系统并发能力。

24.量避免向客户端返回在数据量,若数据量过大,应该考虑相应需求是否合理

相关文章
相关标签/搜索