若是一張表上沒有彙集索引,數據將會隨機的順序存放在表裏。以dbo.SalesOrderDetail_TEST爲例子。它的上面沒有彙集索引,只有一個在SalesOrderID上的非彙集索引。因此表格的每一行記錄,不會按照任何順序,而是隨意地存放在Hash裏。這個時候若是用戶想要找全部單價大於200的銷售詳細記錄,要運行的語句會是:oop
SET STATISTICS PROFILE ON SELECT SalesOrderDetailID , Unitprice FROM SalesOrderDetail_test WHERE UnitPrice > 200
因爲表在UnitPrice上沒有索引,因此SQL SERVER不得不對這個表從頭至尾掃描一遍,把全部UnitPrice的值大於200的記錄一個一個挑出來。性能
從執行計劃裏能夠清楚地看出來SQL SERVER 這裏作了一個表掃描(下圖),後面會詳細介紹如何獲得和分析執行計劃spa
若是這個表上有彙集索引,事情會怎麼樣呢?仍是剛纔那張表作例子,先給它的值是惟一的字段 Unitprice上創建一個彙集索引。這樣全部的數據都會按照彙集索引的順序存儲。3d
CREATE CLUSTERED INDEX SalesOrderDetail_TEST_CL ON dbo.SalesOrderDetail_test (SalesOrderDetailID)
惋惜的是,查詢條件Unitprice上沒有索引,因此SQL SERVER仍是要把全部記錄都掃描一遍。以下圖code
與以前不一樣的是,執行計劃裏的表掃描變成了彙集索引掃描。由於在有彙集索引的表上,數據是直接存放在索引的最底層的,因此要掃描整個表格的數據,就是把整個彙集索引掃描一遍。在這裏,彙集索引掃描就至關於一個表掃描。所要用的時間和資源與表掃描沒有什麼差異。並非說這裏有了」Index」這個字樣,就說明執行計劃比表掃描的有多大進步。固然反過來說,若是看到」Table Scan」的字樣,就說明這個表格上沒有彙集索引。對象
如今在 UnitPrice 上面建一個非彙集索引,看看狀況會有什麼變化blog
CREATE NONCLUSTERED INDEX SalesOrderDetail_TEST_NCL_Price ON dbo.SalesOrderDetail_test (UnitPrice)
再次查詢索引
SET STATISTICS PROFILE ON SELECT SalesOrderDetailID , Unitprice FROM SalesOrderDetail_test WHERE UnitPrice > 200
在非彙集索引裏,會爲每條記錄存儲一份非彙集索引索引鍵的值和一份彙集索引索引鍵的值(在沒有彙集索引的表格裏,是RID值)。因此在這裏,每條記錄都會有一份 SalesOrderDetailID和UnitPrice記錄,按照UnitPrice的順序存放。再查詢,就會看到此次的SQL SERVER不是掃描整個表,會根據新建的索引直接找到符合的記錄的值。ci
可是光用UnitPrice創建在上的索引不能告訴咱們其它字段的值。若是在剛纔那個查詢裏再增長几個字段返回,SQL SERVER 就要先在非彙集索引上找到全部UnitPrice大於200的記錄,而後再根據SalesOrderDetailID的值找到存儲在彙集索引上的詳細數據。這個過程能夠稱爲 「Bookmark Loopup」資源
SET STATISTICS PROFILE ON SELECT SalesOrderId,SalesOrderDetailID , Unitprice FROM SalesOrderDetail_test with(index = SalesOrderDetail_TEST_NCL_Price) WHERE UnitPrice > 200
在SQL SERVER 2005之後,Bookmark Loopup 的動做用一個嵌套循環來完成。因此在執行計劃裏,能夠看到SQL SERVR是先SEEK了非彙集索引,而後再用Clustered Index Seek 把須要的行找出來。這裏的嵌套循環其實就是 Bookmark Loopup 以下圖。
注:Bookmark Loopup就是彙集索引
在SQL SERVER里根據數據找尋目標的不一樣和方法不一樣。有下面幾種狀況。
結構 |
Scan |
Seek |
堆(沒有彙集索引的表) |
Tablescan |
無 |
彙集索引 |
Clustered Index Scan |
Clustered Index Seek |
非彙集索引 |
Index Scan |
Index Seek |
若是在執行計劃裏看到這些動做,就應該可以知道SQL SERVER正在對哪一種對象在作什麼樣的操做。表掃描代表正在處理的表沒有彙集索引,SQL SERVER正在掃描整張表。彙集索引掃描代表SQL SERVER正在掃描一張有彙集索引的表,可是也會是整表掃描。Index Scan代表SQL SERVER正在掃描一個非彙集索引。因爲非彙集索引上通常只會有一小部分字段,因此這些雖然也是掃描,可是代價會比整表掃描要小不少。Clustered Index Seek 和Index Seek會比Scan 說明SQL SERVER正在利用索引結果檢索目標數據。若是結果集只佔表格總數據量的一小部分,Seek 會比Scan便宜不少,索引就起到了提升性能的做用。
瞭解這些是爲之後讀懂執行計劃作基礎。水平有限,暫時爲這些吧。你們能夠多多交流。
下一次會寫統計信息的東西,可能會稍多一些。上述一語句均爲上一次發博客的腳本爲例。