Sql-Server

SQL Server 中非聚集索引的使用

  • July 22, 2019

我有 2 個索引:

CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[TableA]
(
   [Column1] ASC,
   [Column2] ASC
)

CREATE NONCLUSTERED INDEX [IX_2] ON [dbo].[TableA]
(
   [Column3] asc
)

現在我有 2 個更新:

Update TableA SET Column3='' where Column1=''

上面的更新是使用第一個索引,然後使用鍵查找聚集索引

Update TableA SET Column3='' where Column3=''

此更新使用第二個索引

基於更新,我認為我可以刪除第二個索引並使用更新第一個索引

CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[TableA]
(
 [Column1] ASC,
 [Column2] ASC
)
INCLUDE(Column3 asc)

因此,對於更新後的索引,第一次更新工作正常,它使用更新後的非聚集索引,但對於第二次更新,它要求我在 column3 上創建一個非聚集索引。

然後我嘗試了

CREATE NONCLUSTERED INDEX [IX_1] ON [dbo].[TableA]
(
 [Column1] ASC,
 [Column2] ASC,
 [Column3] asc
)

但是對於第二次更新,它仍然要求我創建一個新的非聚集索引。

但是為什麼它要求我創建新的,因為我理解的是Column1, Column2,Column3將出現在非聚集索引的根級別

因此,對於更新後的索引,第一次更新工作正常,它使用更新後的非聚集索引,但對於第二次更新,它要求我在 column3 上創建一個非聚集索引。

更新將始終正常工作。這是您經常執行的更新查詢嗎?

因為通常(額外的)非聚集索引會減慢插入速度。

您的所有數據都在聚集索引 (CIX) 中。非聚集索引 (NCIX) 是聚集索引的副本,但您指定的順序通常與聚集索引不同。

更新 TableA SET Column3=’’ where Column1=''

上面的更新是使用第一個索引,然後使用鍵查找聚集索引

更新 TableA SET Column3=’’ where Column3=''

此更新使用第二個索引

在第一個查詢中,您的伺服器必須查看“Column1=’’”的位置。最快的方法是使用在 Column1 上排序的 NCIX,然後在 CIX 中查找記錄(可能不是)。

在您的第二個查詢中,它使用另一個索引,因為它在 Column3 上排序

基於更新,我認為我可以刪除第二個索引並使用更新第一個索引

不幸的是,沒有,當您包含該列時,它不會用於排序。

創建非聚集索引

$$ IX_1 $$在$$ dbo $$.$$ TableA $$

(

$$ Column1 $$升壓,

$$ Column2 $$升壓,

$$ Column3 $$升序

在這個 NCIX 中,它排在最後,所以它可能沒有很好地排序,伺服器無法快速找到記錄。

看這個例子,我們對 Column1、Column2、Column3 進行排序:

Product      | Category   | Price 
----------------------------------- 
Apple        | Fruit      | 1.10  
Apple pie    | Pastry     | 5.00  
Apple Iphone | Electronic | 899.00  
Apple Watch  | Electronic | 459.00  
Bananas      | Fruit      | 1.50
Pear         | Fruit      | 1.25  
Pineapple    | Fruit      | 2.00  

看看各地的價格如何?甚至“索引”中的第二列也沒有“排序”?

伺服器必須掃描整個索引/表才能找到合適的價格。

這就是為什麼它只在 Column3 上推荐一個新索引。但老實說,除非你經常執行這個查詢,否則不要為此創建索引,更多的索引會使插入和更新花費更長的時間(因為它們都需要最新的值)。

聚集索引:幫助根據鍵列按排序順序將表數據儲存在頁面上。所以你可以說它是排序表(clustered table)。

非聚集索引:在 IAM(索引分配映射)頁面上儲存鍵值以及行地址,如頁面 id 和行偏移量,這有助於查詢以查找數據頁面上的行。

所以你可以說,在 HEAP 或聚集表上創建聚集索引後,你是兩次儲存鍵列的值。一個在數據頁上,另一個在索引頁上。

前任。

你有桌子

CREATE TABLE tbe_TableName
(
Column_1 [datatype],
Column_2 [datatype],
Column_3 [datatype],
Column_4 [datatype],
Column_5 [datatype]
Index IDX_Clus CLUSTERED (Column_1)
)

Column_1 有一個聚集索引 IDX_Clus 和一個非聚集索引。因此 SQL Server 將在數據頁和索引頁中兩次寫入 Column_1 的值。

現在來問你。

執行第一條update語句會在數據庫中兩次寫入值。

  1. 在 IX_2 的索引頁中
  2. 在聚群表的數據庫頁面中

因此優化器從 IDX_1 中查找數據地址的鍵值,並使用鍵查找來查找聚集表的數據頁並將給定值寫入其中。

第二次更新聲明。

與第一條語句幾乎相似,它也會在索引頁和數據頁上寫入兩次值。

即使您將INCLUDEColumn_3 放入索引,也會遵循相同的過程。

注意:在表上創建更多的非聚集索引會佔用更多的磁碟空間並降低寫入性能。

在索引中包含所有列或在表的所有列上創建索引就像數據重複。

因此,我建議您通過 Brent進行昂貴的密鑰查找並做出決定。

謝謝!

引用自:https://dba.stackexchange.com/questions/243425