nvarchar/nchar
何時與 SQL Server 2019 一起使用?
微軟在 SQL Server 2019 中引入了對數據類型的UTF-8 支持,
CHAR
並表示:VARCHAR
此功能可能會顯著節省儲存空間,具體取決於使用的字元集。例如,使用啟用 UTF-8 的排序規則將包含 ASCII 字元串的現有列數據類型從 NCHAR(10) 更改為 CHAR(10),可以將儲存需求減少近 50%。這種減少是因為 NCHAR(10) 需要 22 個字節來儲存,而 CHAR(10) 需要 12 個字節來儲存相同的 Unicode 字元串。
UTF-8 似乎支持所有腳本,所以基本上我們可以開始將 Unicode 數據儲存在
varchar
和char
列中。正如文件中所說,這可以減少表和索引的大小,並且從那裡我們可以獲得更好的性能,因為讀取的數據量更少。我想知道這是否意味著我們可以停止使用實現 UTF-16 的列
nvarchar
?nchar
任何人都可以指出一個場景和理由,不要使用帶有
UTF
編碼的 char 數據類型並繼續使用 n-chars 嗎?
這可以減少表和索引的大小(強調添加)
僅當大多數字元本質上是
[space]
,0 - 9
,A - Z
,a - z
和一些基本標點符號時,才可能縮小大小。在該特定字元集之外(在實際使用中,標準 ASCII 值 32 - 126),您的大小最多等於NVARCHAR
/ UTF-16,或者在許多情況下更大。我計劃遷移數據,因為我相信讀取更少的數據將導致系統性能更好。
當心。UTF-8 並不是一個神奇的“修復一切”開關。在所有其他條件相同的情況下,是的,少讀確實會提高性能。但這裡的“所有其他事物”並不相等。即使僅儲存標準 ASCII 字元(意思是:所有字元都是 1 字節,因此與儲存相比需要一半的空間
NVARCHAR
),使用 UTF-8 也會有輕微的性能損失。我相信這個問題是由於 UTF-8 是一種可變長度編碼,這意味著必須在讀取每個字節時對其進行解釋,以便知道它是一個完整的字元還是下一個字節是它的一部分。這意味著所有字元串操作都需要從頭開始並逐字節進行。另一方面,NVARCHAR
/ UTF-16 始終是 2 字節(即使是補充字元也由兩個 2 字節程式碼點組成),因此可以以 2 字節塊讀取所有內容。在我的測試中,即使只有標準的 ASCII 字元,將數據儲存為 UTF-8 也不能節省經過的時間,但對於 CPU 時間來說肯定更糟。那是沒有數據壓縮,所以至少使用的磁碟空間更少。但是,當使用壓縮時,UTF-8 所需的空間僅小 1% - 1.5%。因此,UTF-8 有效地節省了空間,但 CPU 時間更長。
使用時事情會變得更加複雜,
NVARCHAR(MAX)
因為 Unicode 壓縮不適用於該數據類型,即使該值小到可以儲存在行中。但是,如果數據足夠小,它仍然應該受益於行或頁面壓縮(在這種情況下它實際上變得比 UTF-8 更快)。但是,行外數據不能使用任何壓縮。儘管如此,使表成為聚集列儲存索引確實大大減少了NVARCHAR(MAX)
(即使在使用聚集列儲存索引時它仍然比 UTF-8 略大)。任何人都可以指出一個場景和原因,不要使用帶有 UTF 編碼的 char 數據類型
確實。事實上,在大多數情況下,我並沒有找到一個令人信服的理由來使用它。真正受益於 UTF-8 的唯一場景是:
- 數據主要是標準 ASCII(值 0 - 127)
- 它需要是 Unicode,因為它可能需要儲存比任何單個 8 位程式碼頁上可用的字元範圍更廣的字元(即
VARCHAR
)- 大多數數據都儲存在行外(因此頁面壓縮甚至不起作用)
- 您有足夠的數據需要/想要減少非查詢性能原因的大小(例如減少備份大小,減少備份/恢復所需的時間等)
- 您不能使用聚集列儲存索引(在這種情況下,表的使用可能會使性能變差?)
我的測試表明,在幾乎所有情況下,NVARCHAR 都更快,尤其是當有更多數據時。事實上,21k 行,平均每行 5k 個字元,UTF-8 需要 165 MB,
NVARCHAR
未壓縮需要 236 MB。然而NVARCHAR
,經過的時間快了 2 倍,CPU 時間至少快了 2 倍(有時更多)。儘管如此,它確實在磁碟上多佔用了 71 MB。除此之外,我仍然不建議使用 UTF-8,至少從 CTP 2 開始,因為我在此功能中發現了各種錯誤。
有關此新功能的詳細分析,包括對 UTF-16 和 UTF-8 之間差異的解釋以及這些錯誤的列表,請參閱我的文章: