Sql-Server

使用列儲存索引優化表?

  • June 7, 2021

我是表性能調整的新手。我有一個包含數百萬條記錄的平面表,沒有刪除更新操作。僅插入和讀取操作。

它的結構是這樣的:

目前索引:

PRIMARY CLUSTERED ON (Column1, Column2) –> 因為基於這兩列的唯一性很重要。

查詢將是以下任何一個:

-- query 1
select <all columns> 
from dbo.this_table 
where column1 = 'col1val1'

-- query 2
select < all columns > 
from dbo.this_table 
where Column4= 'col4val1' 
and Column5='col5val2' 
and Column7='col7cval3'

-- query 3
select < all columns > 
from dbo.this_table 
where Column4= 'col4val1' 
and Column6='col6val2' 
and Column7='col7cval3'

-- query 4
select < all columns > 
from dbo.this_table 
where Column4= 'col4val1'

**如何針對 column4、column5、column6、column7 優化我的表?(最後 3 個查詢)**在我的情況下,儲存不是問題,但讀取數據的速度必須最低,所以我正在考慮列儲存。

有人可以建議什麼可以是索引以及以什麼組合?

我總共有 23 列,其中第 4 到 6 列實際上是 7 列。所有這 7 列都是具有重複值的 varchar。預計每個查詢可能會產生 0.01% 到 5% 的表。

column4column5column6和的數據類型是什麼?column7一般來說,這些列的值有多獨特?如果每列中存在高水平的潛在壓縮,列**儲存索引可能對您的案例有用,因為每列的值沒有很大的可變性。**較大的數據集(例如您的表格)通常會出現這種情況,但這確實取決於您,最好的選擇是進行測試。

此外,您的表格有多寬(它有多少列)?因為如果使用傳統的行儲存索引INCLUDE您要選擇的其他列而不是列儲存索引,這將是一個因素。

最後,對於您的每個範例查詢,您估計將返回的表總行數的百分比是多少?

這些都是要考慮並影響不同索引執行情況的因素。關於列儲存索引,您可能還會發現ColumnScore.com有助於確定您的表是否符合列儲存索引的條件。您沒有DELETEUPDATE數據的事實是一個好的開始(儘管也不是硬性要求)。

由於每個表只能使用一個列儲存索引,因此我認為值得嘗試針對最慢的案例進行優化。除非您可以嘗試CREATE NONCLUSTERED COLUMNSTORE INDEX ix_TableName_ColumnNames ON TableName (Column4, Column5, Column6, Column7);作為通用列儲存索引,但如果不進行測試,很難說這將如何滿足您的每個案例。

此外,如果您想嘗試一些額外的行儲存索引,那麼這些將是我的建議作為起點(並且取決於您的表有多少列,可能INCLUDE還會在這些表的其他列中添加一個) :

CREATE NONCLUSTERED INDEX ix_TableName_ColumnNames_2 ON TableName (Column4, Column5, Column7);
CREATE NONCLUSTERED INDEX ix_TableName_ColumnNames_3 ON TableName (Column4, Column6, Column7);

列儲存索引中沒有查找之類的東西。只有掃描。您為索引定義的“鍵”中的列順序完全不相關。

但是, SQL Server可以做的是消除行組。建構列儲存索引時,SQL Server 讀取數據並一次建構 100 萬行的索引 - 這稱為行組。SQL Server 具有每個此類行組中每一列的最低和最高值的元數據。

想像一個查詢有

WHERE col = 23

SQL Server 將查看元數據以確定每個行組中該列的最低和最高值。如果 WHERE 子句中的列值不能存在於行組中,則不必讀取行組。這是行組消除。

您可以嘗試確保數據在這種情況下“對齊”,以便為來列獲得一個很好的行組分組(一個行組中的最低值,另一個行組中的下一個最低值等)。這不是通過鍵中列的順序來完成的,您必須創造性地在創建索引時以何種方式讀取數據。

因此,根據上述情況,您可能會為查詢 2、3 和 4 獲得一些不錯的行組消除,所有這些在 where 子句中都有 column4。假設您在建構索引時對該列進行了很好的對齊。至於查詢 1,除非 col1 和 col4 之間存在順序相關性,否則您可能會對該查詢的列儲存索引進行全面掃描。

接下來要考慮的是列儲存索引是否涵蓋您的查詢(具有查詢引用的所有列)。如果是,則在上述操作之後完成(掃描行組以查找行)。如果沒有,那麼您將進行查找以獲取每一行。如果選擇性低,那麼將會有很多查找,並且對優化器使用其他一些策略可能更有效。

以上是對事物如何工作的簡要說明。其餘的取決於您,因為我們不會使用您的數據和查詢。

此外,進一步的插入最終可能會“降低”索引的質量(在本例中為 column4 的對齊),您將考慮安排重建該列儲存索引是否可行。

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