Performance

使用 varchar 列的複合索引性能

  • February 21, 2020

我有帶有復合非聚集索引的大型事實表,如下所示:

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),如果 usingCHAR(50)除了降低性能之外,我會感到震驚,VARCHAR(50)因為大多數值只使用 20-30 字節。使用CHAR(50)佔用更多空間,減少了適合數據頁的行數,增加了數據頁數,在查詢數據時佔用了緩衝池(即RAM)中的更多空間,加上備份和備份所需的時間更長恢復。而且,如果我沒記錯的話,它還會增加記憶體授予(即每個查詢請求的 RAM),因為它將請求每個欄位 50 個字節而不是 25 個(我相信它請求可變長度欄位的最大大小的 50%)。要更全面地了解使用比您需要的更多空間的下游影響,請參閱:磁碟便宜!奧利?.

話雖如此,在VARCHAR(50)和之間CHAR(50),我會選擇:兩者都不是!鑑於列的名稱,我猜這些實際上是維度?過濾二進制/數字值比過濾字元串快得多(我稍後會提到一個例外)。根據客戶、客戶和項目隨著時間的推移會有多少潛在值,我將使用其中一個INT,或者,如果確實需要,然後BIGINT作為客戶、客戶和項目維度的鍵,並將這些數字鍵值儲存在這裡.

至少,我會將列上的排序規則更改為,因為VARCHARLatin1_General_100_BIN2顯然不需要區分大小寫或重音,否則使用 SHA-256 雜湊的想法甚至不是一個選項。那至少應該能夠以幾乎與INTor一樣快的速度過濾BIGINT(我說“幾乎”只是因為再次為 3 列儲存 20-30 字節值而不是為相同的 3 列儲存 4 或 8 字節值的效果) ,當考慮數百萬/十億行時)。

強烈建議不要在這裡使用任何類型的雜湊值。你不僅會使表格膨脹(即降低性能),而且你會失去這些值的任何意義,因此要麼需要在事實表中儲存這 3 列的非散列值(即瘋狂)或者需要回溯到維度表(在這種情況下,使用INT或使用BIGINT4 或 8 個字節加上沒有計算成本,您將一無所獲!)。

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