1. 程式人生 > 實用技巧 >第六章——根據執行計劃優化效能(2)——查詢表/索引掃描

第六章——根據執行計劃優化效能(2)——查詢表/索引掃描

前言:

在絕大部分情況下,特別是從一個大表中返回少量資料時,表掃描或者索引掃描並不是一種高效的方式。這些必須找出來並解決它們從而提高效能,因為掃描將遍歷每一行,查詢符合條件的資料,然後返回結果。這種處理是相當耗時耗資源的。在效能優化過程中,一般集中於:

1、 CPU

2、 Network

3、 磁碟IO

而掃描操作會增加這三種資源的開銷。

準備工作:

下面將建立兩個表來檢視不同的物理關聯操作的不同影響。建立指令碼已經在本系列的第一篇中給出,這裡不再顯示。

步驟:

1、 開啟執行計劃並執行下面查詢:

[sql] view plaincopyprint?

  1. SELECTsh.*

  2. FROMSalesOrdDetailDemoAS

    sd

  3. INNERJOINSalesOrdHeaderDemoASshONsh.salesorderID=sd.salesorderid

  4. WHEREsh.orderdate='2004-07-3100:00:00.000'

  5. GO


從執行計劃的截圖可以看到兩表均使用了表掃描,其中執行計劃建議了丟失索引。此時應該考慮是否有必要建立:

2、 為了避免表掃描,建立一個聚集索引在表SalesOrdHeaderDemo中:

[sql] view plaincopyprint?

  1. CREATEUNIQUECLUSTEREDINDEXidx_salesorderheaderdemo_SalesOrderIDONsalesordheaderdemo(SalesOrderID)

  2. GO


3、 再次執行步驟1中的查詢,看看執行計劃是否已經移除了表掃描:

4、 上圖中可以看到建立了聚集索引的表已經變成了聚集索引掃描,但是未建立的就還是表掃描,觀察聚集索引掃描,它只是把表掃描換成了聚集索引掃描,所以沒有很大的效能提升。

5、 現在繼續把第二個表的表掃描去掉,通過建立在這個表上的唯一聚集索引:

[sql] view plaincopyprint?

  1. CREATEUNIQUECLUSTEREDINDEXidx_SalesDetail_SalesOrderIDONSalesOrdDetailDemo(SalesOrderID,SalesOrderDetailID)

  2. GO


6、 再次執行查詢。

7、 下面截圖中可以看到表掃描已經徹底移除:

分析:

在深入討論之前,首選需要澄清的是,掃描並不總是壞的,而查詢並不總是好的,但是在絕大部分情況下,特別是在大表中返回少量資料時,查詢會有更好的效能表 現。同樣,並不總是有方法在每個查詢中移除掃描操作。如果查詢的效能問題是因為掃描,那麼移除掃描操作會更好,否則,看看是否有什麼改變方式去提高效能。

在第一步中,因為兩表均沒有索引,所以優化器只能選擇掃描來查詢資料。

在第三步中,已經建立了一個聚集索引在SalesOrdHeaderDemo表上,表掃描變成了聚集索引掃描,聚集索引查詢是我們希望得到的結果,但是因為我們沒有什麼謂詞在第一個表上,所以只能掃描整個聚集索引來代替掃描整個表。

在第六步中,在第二個表也建立了聚集索引,且有一個謂詞在這個表上,所以出現了聚集索引查詢,而不是聚集索引掃描。


轉載於:https://blog.51cto.com/rmlifejun/1678097