上接SQL Server 查询性能优化——索引与SARG(二)
2 请不要进行负向查询
除了不应该对字段数据进行计算外,非SARG 语句的格式语句还包含在WHERE条件子句中,使用负向查询操作符。
如NOT 、!=、<> 、!>、!<、NOT EXISTS 、NOT IN及NOT LIKE 等,因为通过有顺序的索引结构,SQL SERVER 可以有效地利用二分法进行查找,快速找到相应的数据,但是如果查询条件是不要什么数据,其余的都要(就是负向查询), 则 无法利用索引进行二分查找,只能进行全表扫描或聚集索引扫描。
以下同样是负向操作健立的SARG 条件查询与非SARG 条件查询范例。从中可以看出两者的执行成本是不一样的,相差十倍左右,但是其数据查询的记录数量也不一样。个人理解查询优化程序是根据数据查询的记录数量,来决定使用哪种执行计划。
逻辑读 |
执行成本 | ||||
SELECT * FROM [WBK_PDE_ LIST_ORG_ HISTROY] where QTY_1=312
|
有主键(索引1,索引2) |
1 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取137 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。 |
137 |
|
0.121935 |
|||||
无主键(索引2) |
2 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取43 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
43 |
||
0.121935 |
|||||
SELECT * FROM [WBK_PDE_ LIST_ORG_ HISTROY] where QTY_1<>312
|
有主键(索引1,索引2) |
3 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取1314 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
1314 |
|
1.03687 |
|||||
无主键(索引2) |
4 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取1306 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
1306 |
||
1.03687 |
|||||
小结:
查询语句 |
逻辑读 |
查询记录数量 |
执行成本 |
1 |
137 |
37 |
0.121935 |
2 |
43 |
37 |
0.121935 |
3 |
1314 |
60796 |
1.03687 |
4 | 1306 | 60796 | 1.03687 |
3 不要在WHERE子句中对字段使用函数
在查询语句中对字段使用函数,就是对字段数据进行计算,所以这些都不算是SARG。使用函数之后 ,SQL SERVER 需要将数据表内所有记录的相关字段输入到函数中,如果有100万条记录,就需要调用函数100万次,这将是性能杀手。
下面列出两个非SARG与SARG的查询成本区别的示例。
逻辑读 |
||||
SELECT * FROM [WBK_PDE_LIST_ORG_HISTROY] where dbo.f_qty(QTY_1,G_QTY)=400 |
||||
数值函数计算 |
1 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取1428 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
1428 |
|
1.03687 |
||||
SELECT * FROM [WBK_PDE_LIST_ORG_HISTROY] where QTY_1=200 and G_QTY=200 |
||||
2 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取428 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
428 |
||
0.42645 |
||||
SELECT * FROM [WBK_PDE_LIST_ORG_HISTROY] where dbo.[f_ByteLeft](wbook_no,14)='BE404942450013' |
||||
字符函数计算 |
3 |
表'Worktable'。扫描计数0,逻辑读取0 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。 表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数2,逻辑读取850 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。 |
850 |
|
1.03904 |
||||
SELECT * FROM [WBK_PDE_LIST_ORG_HISTROY] where wbook_no='BE404942450013' |
||||
4 |
表'WBK_PDE_LIST_ORG_HISTROY'。扫描计数1,逻辑读取3 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。
|
3 |
||
0.0033071 |
||||
小结:
查询语句 |
逻辑读 |
查询记录数量 |
执行成本 |
1 |
1428 |
3873 |
1.03687 |
2 |
136 |
37 |
0.42645 |
3 |
850 |
3873 |
1.03904 |
4 | 3 | 22 | 0.0033071 |