時間過得真快——再過幾分鐘,你就要完成第2個月的性能調優培訓。今天這部分培訓我想講下非聚集索引的更多信息,還有你會碰到它的一些負作用。
上一星期我們討論了SQL Server里的書簽查找,它是非常危險的。在執行計劃里SQL Server訪問非聚集索引時,額外列必須要從表本身獲取時(因為它們不是非聚集索引的一部分),書簽查找會發生。如果你想避免書簽查找,你可以在SQL Server里定義覆蓋索引(Covering Index) 。我們來看下。
覆蓋索引(Covering Index)在SQL Server里覆蓋索引是傳統的非聚集索引。唯一的區別是覆蓋非聚集索引可以包含給出查詢所有需要的列。這就是說使用覆蓋索引可以避免書簽查找。我們來看一個非常簡單的例子。下列的查詢會產生書簽查找,因為PostalCode列不是非聚集索引IX_Address_StatePRovinceID的一部分,在執行計劃里,這個非聚集索引已被使用。
1 SELECT2 AddressID,3 PostalCode4 FROM Person.Address5 WHERE StateProvinceID = 426 GO
這個查詢本身產生18個邏輯讀。你可以通過定義覆蓋非聚集索引,拿掉這個查詢的書簽查找。就是說,我們需要包含PostalCode列,在非聚集索引的葉子層。
1 CREATE NONCLUSTERED INDEX idxAddress_StateProvinceID ON2 Person.Address (StateProvinceID)3 INCLUDE (PostalCode)4 GO
當你再次執行這個查詢時,從執行計劃里你可以看到書簽查找已經不見了,SQL Server使用索引查找(非聚集索引)運算符。邏輯讀減少為2個。非常顯著的性能提升!
唯一你要知道的是,并不是每個書簽查找都是非常危險的。我們的目標不是移除每個書簽查找,只有壞的才移除。
臨界點(Tipping Point)在一些情況下,當SQL Server對指定查詢進行書簽查找操作時,它可以決定書簽查找太耗資源了(根據必須的邏輯讀)。在那個情況下,SQL Server會進行全表掃描,而忽略所有的非合格列。做出這個決定點位置,在SQL Server里被稱為臨界點(Tipping Point)。臨界點就是SQL Server用來決定是進行書簽查找還是全表掃描。
臨界點躲在你查詢需要讀取頁數的1/4到1/4的某個位置。這和你需要讀取的記錄數無關(因為記錄的大小決定了1頁里你可以存放多少記錄)。對于這個非常簡單的例子,我定義的表里每條記錄長度是400 bytes長,這就是在8k的頁里可以存放20條記錄。另外我在Value列定義了一個非聚集索引。下面的查詢使用書簽查找返回1061條記錄。
1 SELECT * FROM Customers2 WHERE Value < 10623 GO
如果獲取更多一條記錄,作為特殊情況的下面查詢就會臨界點上,然后SQL Server就會掃描整個表。
1 SELECT * FROM Customers2 WHERE Value < 10633 GO
2個近乎一樣的查詢,卻有完全不同的執行計劃!這在某些情況下會是個巨大的問題,因為你的計劃穩定性不再。過去幾年我與很多不同客戶打交道時,因為這個問題,它們的SQL Server近乎發瘋。SQL Server臨界點游戲——為什么非聚集索引被忽略!
小結在這一部分的性能調優培訓里,你學習了SQL Server里的覆蓋非聚集索引還有臨界點。在你學習的4個星期里,索引在SQL Server里可以說是個很神奇的東西!
每個索引在提高你讀性能的同時,也會降低你的寫性能。在你執行INSERT, UPDATE和DELETE語句時,每個索引都由SQL Server全權負責維護。因此,你要基于讀需求和寫工作量來平衡你的索引策略。
接下來的4個星期,我們會聚焦更多SQL Server里的執行計劃,你會學到如何讀懂和理解執行計劃,還有它們如何用來做性能調優。請繼續關注,下周見!
新聞熱點
疑難解答