Sql-Server

SQL Server 中關於 varchar 大小調整的目前最佳實踐是什麼?

  • July 3, 2018

我試圖從儲存和性能角度了解決定 varchar 列應該有多大的最佳方法。

性能

根據我的研究,似乎varchar(max) 僅在您確實需要時才應使用;也就是說,如果該列必須容納超過 8000 個字元,一個原因是缺乏索引(儘管我一般對 varchar 欄位的索引有點懷疑。不過我對 DB 原則還是很陌生,所以這可能是沒有根據的)和壓縮(更多的儲存問題)。事實上,一般來說,人們似乎建議只使用你需要的東西,當做 varchar(n)….oversized 是不好的,因為查詢必須考慮最大可能的大小。但也有人指出,引擎將使用指示大小的一半作為數據平均實際大小的估計值。這意味著人們應該從數據中確定平均大小是多少,將其加倍,並將其用作 n。但是對於具有非常低但非零變異性的數據,這意味著比最大尺寸大 2 倍,這看起來很多,但也許不是?見解將不勝感激。

儲存

在閱讀了行內儲存與行外儲存的工作原理並記住實際儲存僅限於實際數據之後,在我看來,實際上 n 的選擇對儲存幾乎沒有影響(除了確保它足夠大以容納所有東西)。即使使用 varchar(max) 也不應該對儲存產生任何影響。相反,如果可能,目標可能是將每個數據行的實際大小限制為 ~8000 字節。這是對事物的準確解讀嗎?

上下文

我們的一些客戶數據波動不大,所以我們通常使列比它們需要的寬一點,比如這些列大 15-20%。我想知道是否還有其他特殊考慮;例如,與我一起工作的人告訴我使用 2^n - 1 個尺寸(雖然我沒有發現任何證據……)

我說的是初始表創建。客戶會告訴我們,他們將開始向我們發送一個新表,並發送樣本數據(或只是第一個生產數據集),我們查看這些數據並在我們端製作一個表來保存數據。我們想在我們這邊製作表格來處理未來的進口以及樣本中的內容。但是,某些行肯定會變長,所以我們填充它們。

問題是多少錢,有技術指導嗎?

無論具體的數據類型如何,您都需要能夠儲存應用程序請求儲存的任何內容。您不能指定小於實際保存的最大大小的內容。

您也不需要也不想指定大於將要儲存的最大實際大小的列長度,原因有很多:查詢記憶體分配,可能會填滿最大行大小,並且不會留下任何空間來添加列未來等

誠然,可變長度字元串和二進制列不具有固定長度數據類型(字元串/二進制/數字/日期/等)所具有的儲存含義(儘管其中一些含義可以通過數據壓縮或使用SPARSE列定義來消除)選項)。但是,正如您所指出的,即使沒有直接儲存影響,仍然存在高估查詢所需記憶體的性能影響。

理智點。只使用你需要的東西。如果在不久的將來很可能需要增加列長度,則可以考慮,但請記住,擴大列的大小比減小列的大小更容易。是的,將涉及一些工作,但由於該工作僅僅是“潛在的”,而過大的性能影響是“實際的”,通常最好根據您實際需要的內容定義列,而不是您可能需要的內容-sorta認為您將來可能需要。許多談論的變化從未發生,而且通常無法預見所需的變化。跟著你知道的走。

相反,如果可能,目標可能是將每個數據行的實際大小限制為 ~8000 字節。

我不確定你在這裡得到什麼。SQL Server 會在物理上將您限制在 8000 多字節。使用 LOB 類型 — VARCHAR(MAX)NVARCHAR(MAX)VARBINARY(MAX)XML和不推薦使用TEXT的 、NTEXTIMAGE類型 — 允許超出初始頁面大小限制,但這只是由於放置了一個指針(16 個或更多字節,取決於類型,並取決於使用類型時儲存在行外的值的大小MAX)。數據頁的實際物理限制沒有改變。

您的目標應該是使用最少的物理空間來儲存應用程序/業務需要儲存的內容,而不會破壞或截斷不完整的值,從而使不完整的值失去意義或導致下游問題。如果您需要儲存 12,000 個字元的東西,請使用,VARCHAR(MAX)因為這是需要的。如果您要儲存電話號碼或郵政/郵政編碼,那麼使用 是不明智的VARCHAR(100),也是不負責任的VARCHAR(MAX)

我們的一些客戶數據會有一點波動,因此我們通常會為這些列設置比所需的稍寬的列,例如大 15-20%。我想知道是否還有其他特殊考慮;

不是所有系統都至少有一些波動的數據嗎?任何儲存人名的系統都符合條件,對吧?名稱的長度存在相當大的差異。然後你有像王子這樣的人去把他們的名字改成一個符號,現在你有一個完全不同的問題,不是長度。事情就是這樣。

但是,吹噓一下:“比需要的值大 15-20%”的值怎麼可能不是實際需要的值呢?假設有一個關於添加新列的討論,有人建議 50 個字元,然後其他人說,“嗯,60 個多 20%,所以我們做 60 個,因為有人可能有 60 個。” 如果客戶可能擁有 60 是真的,那麼 60 是並且一直是實際需要的值,而 50 始終是錯誤的。

當然,如果有一些關於數據來源的跡象會有所幫助,因為:

  1. 如果您將“URL”設為 1024 並且有人需要 1060,那麼它必須是 1060(類似地,如果您創建 URLVARCHAR並抱怨它弄亂了現在在域名中允許的 Unicode 字元,那麼它必須是NVARCHAR),但
  2. 如果有人想在 500 個字元限制的評論欄位中添加 1000 個字元,那麼它仍然只需要500 個。人們可以在評論中不那麼冗長(對我來說是一個巨大的挑戰;-),但ProductSKU最好足夠大以適應所有人客戶的 SKU。

我說的是初始表創建。客戶會告訴我們,他們將開始向我們發送一個新表,並發送樣本數據(或只是第一個生產數據集),我們查看這些數據並在我們端製作一個表來保存數據。我們想在我們這邊製作表格來處理未來的進口以及樣本中的內容。但是,某些行肯定會變長,所以我們填充它們。問題是多少錢,有技術指導嗎?

你在這裡做了很多假設。當然,有些領域可能會變得更大。但話又說回來,他們可能不會。或者,有些可能會變小。有些人可以從非 Unicode 變為 Unicode(一旦他們意識到世界變得越來越小,並且不能假設姓氏只會有基本的 ASCII/美國英文字元)。或者,他們可以停止發送欄位。或者他們可以在將來添加一個或多個欄位。這個和其他東西的任何組合。那麼為什麼只關注VARCHAR列呢?如果他們目前正在發送一個INT值並且在一兩年內達到最大值並開始發送一個值BIGINT怎麼辦?如果他們有一個值為 0 - 5 的“狀態”欄位怎麼辦。你只是假設INT哪個是“填充的”,因為它允許增長,但可能應該是TINYINT

唯一可以安全預測的是,試圖預測客戶數據將如何變化的錯誤往往多於正確。正確是運氣/巧合的問題(如果不是運氣,那就去玩彩票吧;)。

所以指導方針是:

  1. 不要浪費時間和精力試圖回答一個無法回答的問題。
  2. 相反,專注於盡可能多地獲取有關客戶實際數據的資訊,然後繼續進行(即數據驅動的決策制定;-)。

您已經有了範例數據,太好了。但是,請不要忘記您還有客戶的聯繫資訊:電話和/或電子郵件。聯繫他們!詢問他們的數據規格(就像您的系統一樣,他們系統中目前的數據最大長度可能為 35,但他們的系統將其定義為VARCHAR(50),並且他們的系統將接受該長度,在這種情況下您應該使用50)。並且,詢問他們是否有任何改變這些數據類型(類型和/或大小)的近期計劃。

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