2013年5月27日 星期一

效能調校(4)-善用覆蓋索引

通常大家都知道,在資料庫加入索引,可以增進查詢效率。可是若將查詢欄位加上了索引之後,為什麼使用到 RowNumber() 進行查詢時,效率還是很慢? 在說明之前,可先參考這篇,瞭解索引的類型。

下面這二個例子,CreatedTime 和 RevisedTime 這二個欄位都有建立 NonClustered-Index,但分別以該欄位進行排序搜尋後的結果,二者效能上卻差了10倍以上。 問題就在於,這二個索引之中,CreatedTime 欄位沒有使用內含資料行。

使用圖行執行計畫時,最佳化工具會自動判斷是否有缺少內含資料行,若有則會出現「使用遺漏索引資訊(Missing Index Information)」。 當發生遺漏索引時,查詢引擎無法有效利用索引鍵值找到其他欄位資料的位置。

例一:沒使用內含資料行的索引

CREATE NONCLUSTERED INDEX IX_tblUser_CreatedTime ON dbo.tblUser(CreatedTime desc) 
 
SELECT TOP 10 * FROM 
(
	SELECT ROW_NUMBER() OVER ( ORDER BY CreatedTime) AS RowNumber, *
	FROM (
		SELECT U.UserID, U.UserName, CN1.CodeName as Sex, Birthday,
		U.CreatedTime, U.RevisedTime FROM tblUser U WITH (NOLOCK)
		LEFT JOIN tblCodeName CN1 WITH (NOLOCK) ON U.Sex=CN1.Code AND CN1.CodeType='0001'
		WHERE 1=1  
	) A
) B 
WHERE RowNumber > 3276820

例二:使用內含資料行的索引

CREATE NONCLUSTERED INDEX IX_tblUser_RevisedTime ON dbo.tblUser(RevisedTime desc) 
INCLUDE (UserID,UserName,Sex,Birthday,CreatedTime)

SELECT TOP 10 * FROM 
(
	SELECT ROW_NUMBER() OVER ( ORDER BY RevisedTime) AS RowNumber,*
	FROM (
		SELECT U.UserID, U.UserName, CN1.CodeName as Sex, Birthday,
		U.CreatedTime, U.RevisedTime FROM tblUser U WITH (NOLOCK)
		LEFT JOIN tblCodeName CN1 WITH (NOLOCK) ON U.Sex=CN1.Code AND CN1.CodeType='0001'
		WHERE 1=1  
	) A
) B 
WHERE RowNumber > 3276820

1.無任何索引

2.nonclustered-index(NP_ID)

3.clustered-index(NP_ID)

4.index(NP_ID) include(CHT_NAME) , PS.叢集索引無法指定Include

沒有留言:

張貼留言