使用 varchar 列的複合索引性能
我有帶有復合非聚集索引的大型事實表,如下所示:
NONCLSUTERED INDEX (OrderDate,OrderType,ClientKey,ItemKey,CustomerKey)
以“Key”結尾的列是 varchar(50) 列,但它們儲存 20-30 個字元的字元串。
從長遠來看,我是否需要擔心索引中的 varchar 列的長度實際上是不同的?當數百萬行合併到這些表中時,我會得到更多的頁面拆分、更慢的性能嗎? https://stackoverflow.com/questions/59667/what-are-the-use-cases-for-selecting-char-over-varchar-in-sql
由於列的長度不同,Sql Server 引擎是否更難使用該索引找出計劃?我讀到 CHAR 更好,因為它的大小固定,並且 db 引擎更容易計算,因此它的性能更好。有那麼重要嗎?
使用 SHA2_256 函式單獨散列這些“Key”列是否值得,所以它們變成固定大小的 BINARY(32)?
NONCLSUTERED INDEX (OrderDate,OrderType,HASHEDClientKey,HASHEDItemKey,HASHEDCustomerKey)
我做了我的測試,至少回答了性能問題,並且沒有看到雜湊鍵比 varchar 有任何性能優勢。事實上,計算雜湊並將每個額外的 32 個字節儲存在原始“Key”列旁邊是一個很大的成本。
我無法測試的是,當我每天將數百萬行合併到表中時,這些 varchar 索引將如何表現?
從性能和維護的角度來看,您會選擇哪一個?
雖然某些 RDBMS 可能被調整為與固定長度字元串更好地互動(我似乎記得 DB2/MVS 可能在固定長度字元串方面做得更好,但我在 1996 年了解到這一點,它是大型機 DB2,所以不確定是否如此應用於 Unix 或 Windows 上的 DB2),如果 using
CHAR(50)
除了降低性能之外,我會感到震驚,VARCHAR(50)
因為大多數值只使用 20-30 字節。使用CHAR(50)
佔用更多空間,減少了適合數據頁的行數,增加了數據頁數,在查詢數據時佔用了緩衝池(即RAM)中的更多空間,加上備份和備份所需的時間更長恢復。而且,如果我沒記錯的話,它還會增加記憶體授予(即每個查詢請求的 RAM),因為它將請求每個欄位 50 個字節而不是 25 個(我相信它請求可變長度欄位的最大大小的 50%)。要更全面地了解使用比您需要的更多空間的下游影響,請參閱:磁碟便宜!奧利?.話雖如此,在
VARCHAR(50)
和之間CHAR(50)
,我會選擇:兩者都不是!鑑於列的名稱,我猜這些實際上是維度?過濾二進制/數字值比過濾字元串快得多(我稍後會提到一個例外)。根據客戶、客戶和項目隨著時間的推移會有多少潛在值,我將使用其中一個INT
,或者,如果確實需要,然後BIGINT
作為客戶、客戶和項目維度的鍵,並將這些數字鍵值儲存在這裡.至少,我會將列上的排序規則更改為,因為
VARCHAR
您Latin1_General_100_BIN2
顯然不需要區分大小寫或重音,否則使用 SHA-256 雜湊的想法甚至不是一個選項。那至少應該能夠以幾乎與INT
or一樣快的速度過濾BIGINT
(我說“幾乎”只是因為再次為 3 列儲存 20-30 字節值而不是為相同的 3 列儲存 4 或 8 字節值的效果) ,當考慮數百萬/十億行時)。我強烈建議不要在這裡使用任何類型的雜湊值。你不僅會使表格膨脹(即降低性能),而且你會失去這些值的任何意義,因此要麼需要在事實表中儲存這 3 列的非散列值(即瘋狂)或者需要回溯到維度表(在這種情況下,使用
INT
或使用BIGINT
4 或 8 個字節加上沒有計算成本,您將一無所獲!)。