除了不应该做字段数据的计算外,非SARG 语句的格式语句还包含在WHERE条件子句中,使用负向查询操作符。 如NOT 、!=、 、!、!、NOT EXISTS 、NOT IN及NOT LIKE 等,因为通过有顺序的索引结构,SQL SERVER 可以有效地利用二分法进行查找,快速找到相应的数据,但是如果查询条件是不要什么数据,其余的都要(就是负向查询), 则 无法利用索引进行二分查找,只能进行全表扫描或聚集索引扫描。 以下同样是负向操作健立的SARG 条件查询与非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 |
| | | |