上接SQL Server 查詢效能最佳化——索引與SARG(三)
說明:下文中所說的建立索引都是SQL Server 查詢效能最佳化——索引與SARG(一)中開頭部分所說明的索引列表中的索引。
例:下面表格中說的索引1(叢集索引)和索引5(非叢集索引)
4: 小心使用OR操作符
如上文SQL Server 查詢效能最佳化——索引與SARG(三)中的例子中WBK_PDE_LIST_ORG_HISTROY表建立了索引2,即在[QTY_1] 欄位建立索引,通過該索引.就可以從大量記錄中.快速找出符合記錄的記錄(如上文中的“2 請不要進行負向查詢”中表格中的序號2,邏輯讀取43次,執行成本0.121935),再在少量的資料過濾COP_G_NO='60207106'的記錄,因此可以發揮索引的功能。但若使用的是OR 操作,則需要所有欄位都有索引可用,查詢語句改成如下:
SELECT * FROM [WBK_PDE_LIST_ORG_HISTROY] where qty_1=312 or COP_G_NO='60207106'
而當COP_G_NO欄位沒有適用索引時,直接掃描整個資料表。
|
序號 |
|
邏輯讀 |
執行成本 |
查詢語句 |
|
SELECT [WBOOK_NO] ,[COP_G_NO],[G_NO],[CODE_T],[QTY_1],[UNIT_1] ,[TRADE_TOTAL],[GROSS_WT] FROM [WBK_PDE_LIST_ORG_HISTROY] where qty_1=312 or COP_G_NO='60207106' |
|
|
索引2 |
1 |
表'WBK_PDE_LIST_ORG_HISTROY'。掃描計數1,邏輯讀取1306 次,物理讀取0 次,預讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。 |
1306 |
|
|
|
1.03687 |
索引2,3 |
2 |
表'WBK_PDE_LIST_ORG_HISTROY'。掃描計數2,邏輯讀取101 次,物理讀取0 次,預讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。 |
101 |
|
|
|
0.245731 |
索引4,5 |
3 |
表'WBK_PDE_LIST_ORG_HISTROY'。掃描計數2,邏輯讀取6 次,物理讀取0 次,預讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。 |
6 |
|
|
|
0.0125617 |
|
|
|
|
|
小結:
序號 |
所建立的索引 |
邏輯讀 |
查詢記錄數量 |
執行成本 |
1 |
索引2 |
1306 |
90 |
1.03687 |
2 |
索引2,3 |
101 |
92 |
0.245731 |
3 |
索引4,5 |
6 |
92 |
0.0125617 |
從小結中所列的表格中,可以看出由於索引4,索引5使用了include關鍵字,在建立索引時把查詢語句中需要中的欄位添加到了非叢集索引的葉級,從而在進行查詢時只需要訪問到索引的葉級就可以,不需要通過RID操作去訪問資料頁中的資料,所以提高了查詢速度。
就是說查詢最佳化工具可以在索引中找到所有列值;不訪問表或叢集索引資料,從而減少磁碟 I/O 操作。但這樣做的壞處是索引需要額外的磁碟儲存空間。是優是劣,按實際情況進行調整。
例外情況:
使用OR操作符時,如果多個條件中有一個條件沒有合適的索引,則其他條件都有索引也是沒有用處的,只有整個資料表進行掃描或進行叢集索引掃描,以確定全部的資料是否有符合的記錄。
即使多個條件都有索引,所需要的查詢結果數量過多,SQL SERVER查詢最佳化程式將自動採用全表掃描或叢集索引掃描,以確定全部的資料是否有符合的記錄。
如下例:
建立非叢集索引4,5,沒有索引1。
執行以下代碼
SELECT [WBOOK_NO] ,[COP_G_NO],[G_NO],[CODE_T],[QTY_1],[UNIT_1],[TRADE_TOTAL],[GROSS_WT] FROM [WBK_PDE_LIST_ORG_HISTROY] where qty_1=2 or COP_G_NO='60207106'
表'WBK_PDE_LIST_ORG_HISTROY'。掃描計數1,邏輯讀取1306 次,物理讀取0 次,預讀0 次,lob 邏輯讀取0 次,lob 物理讀取0 次,lob 預讀0 次。
總結:
不要認為只要有負向查詢出現在查詢條件WHERE子句中就一定認為索引就沒有效用,在WHERE子句中使用非SARG並不一定導致全表掃描或是叢集索引掃描。SQL SERVER可以在某些非SARG狀況中使用索引,以及查詢中雖然包含了部分非SARG但仍可以對此查詢中的SARG部分使用索引。
也不要認為在查詢語句中的查詢條件WHERE子句中使用SARG就一定會使用到相應的索引,而不會進行全表掃描或叢集索引掃描。SQL SERVER查詢最佳化程式會根據SARG使用方式所擷取的查詢結果的記錄數量是否過多,而決定是使用相應的索引,還是使用全表掃描或是叢集索引掃描。當然,無論情況如何,在進行效能調校時,最先也是最直接的改變就是把非SARG改成SARG。因為把非SARG改成SARG最壞的情況就是全表掃描或是叢集索引掃描,查詢結果的記錄數量比較少,會高效利用相應索引,快速查出結果。