1. 程式人生 > >sql server 資料庫優化--顯示執行計劃 你真的知道索引使用???

sql server 資料庫優化--顯示執行計劃 你真的知道索引使用???

首先在PRID欄位上建立非聚集索引。

CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID
ON PerformanceIssue (PRID)
GO

執行下面語句並檢視執行計劃的結果。

Select PRID, PRCode, PRDesc
From PerformanceIssue
GO

奇怪了,“Table Scan”仍然用到了。為什麼SQL Server沒有用到那個非聚集索引?於是繼續優化查詢語句,選擇檢索兩個欄位 [PRID, PRCode] 。

Select PRID, PRCode From PerformanceIssue
GO

執行結果是和上一個查詢結果一摸一樣。於是修改查詢為只檢索一個欄位 [PRID] 。

Select PRID
From PerformanceIssue
GO

執行計劃結果如下:

“Index Scan”在查詢中被用到了,這很好。很自然,接下來的問題就是“Index Scan”什麼時候會被用到。欄位PRID上有一個索引,查詢語句中選中的欄位為PRID。執行查詢的時候,SQL Server掃描索引頁,因此用到了“Index Scan”方法。前面的查詢中選擇了有索引的和沒有索引的欄位,SQL Server無法使用“Index Scan”。當查詢中只選擇有索引的欄位時,SQL Server就使用了“Index Scan”。我不清楚SQL Server底層到底是如何判斷的,不過通過這些試驗,我認為當查詢中只選擇有索引的欄位時,SQL Server就使用“Index Scan”方法

下面看“Index Seek”方法何時產生。當我看到“Seek”這個詞時,第一反應就是條件查詢這個主意。

我嘗試三種不同的帶WHERE語法的查詢語句,以找出那種會用“Index Seek”。第一種語句如下:

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRCode = 8
GO

結果顯示,執行計劃使用了“Table Scan”。

第二種語句如下:

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRDesc = ' PerformanceIssue - 8'
GO

執行計劃仍然使用“Table Scan”方法。

第三種查詢語句如下:

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'

-- PRID GUID value might be differ in your machine
GO


查詢用到了“Index Seek”和“Bookmark Lookup”方法。用到“Index Seek”是因為WHERE後面使用帶索引的欄位PRID來進行過濾。“Bookmark Lookup”方法被用到是因為查詢中選擇了沒有索引的欄位。如果去掉這兩個沒有索引的欄位,那麼“Bookmark Lookup”方法就可以去掉。當然如果只返回PRID欄位,那麼該查詢就沒什麼意義了,因為WHERE語句後面已經給出PRID具體取值了。

我認為“Index Seek”在效能改善上比“Index Scan”和“Table Scan”要好,這主要表現在下面幾個方面:

  1. “Index Seek”不需要對錶和索引頁進行掃描;而“Table Scan”和“Index Scan”需要。
  2. “Index Seek”利用“WHERE”來過濾獲取的資料,這樣比用“Index Scan”和“Table Scan”快很多。

當我完成這些測試後,我同事問我一個很有意思的問題:SQL Server什麼時候使用“Clustered Index Scan”和“Clustered Index Seek”?下面對“Clustered Index Scan”和“Clustered Index Seek”進行實驗。

我決定在PRCode上建一個聚集索引來測試“Clustered Index Scan”和“Clustered Index Seek”。