Sql-Server

varchar(255) 還是 varchar(256)?

  • January 22, 2021

我應該使用varchar(255)還是varchar(256)在設計表格時使用?我聽說一個字節用於列的長度,或用於儲存元數據。

這個時候還重要嗎?

我在網際網路上看到了一些文章,但它們適用於 Oracle 和 MySQL。

我們有 Microsoft SQL Server 2016 企業版,它是如何應用到這個環境中的?

現在舉例來說,如果我告訴我的客戶保留例如 255 個字元而不是 256 個字元的文本描述,有什麼區別嗎?我讀到的“最大長度為 255 個字元,DBMS 可以選擇使用單個字節來指示欄位中數據的長度。如果限制為 256 或更大,則需要兩個字節。” 這是真的?

適當調整每一列的大小。不要為每列使用“標準”大小。如果您只需要 30 個字元,為什麼要創建一個可以處理 255 個字元的列?我很高興你不提倡使用varchar(max)你的字元串列。

如果您需要對列進行索引,或者如果您將列用作主鍵並且它具有外鍵引用,則這是特別謹慎的建議。SQL Server 使用其查詢優化器中每列的大小來了解查詢處理的估計記憶體需求。擁有過大的列可能會損害性能。

過大的列上的索引可能會導致生成錯誤:

CREATE TABLE dbo.WideIndex
(
   col1 varchar(255) NOT NULL
   , col2 varchar(255) NOT NULL
   , col3 varchar(600) NOT NULL    
);

CREATE INDEX IX_WideIndex_01
ON dbo.WideIndex (col1, col2, col3);

嘗試在上面創建索引會導致此警告:

警告!最大密鑰長度為 900 字節。索引“IX_WideIndex_01”的最大長度為 1110 字節。對於較大值的某些組合,插入/更新操作將失敗。

900 字節是聚集索引(以及 SQL Server 2012 和更早版本上的非聚集索引)的最大鍵大小。1700 字節是較新版本的 SQL Server 上非聚集索引的最大鍵大小。如果您設計具有通用寬度的列,例如 (255),您可能會比預期更頻繁地遇到此警告。

如果您對儲存內部結構感興趣,可以使用以下小測試來更好地了解 SQL Server 如何儲存未壓縮的行儲存數據。

首先,我們將創建一個表,我們可以在其中儲存各種大小的列:

IF OBJECT_ID(N'dbo.varchartest', N'U') IS NOT NULL
DROP TABLE dbo.varchartest;
GO

CREATE TABLE dbo.varchartest
(
   varchar30 varchar(30) NOT NULL
   , varchar255 varchar(255) NOT NULL
   , varchar256 varchar(256) NOT NULL
);

現在我們將插入一行:

INSERT INTO dbo.varchartest (varchar30, varchar255, varchar256)
VALUES (REPLICATE('1', 30), REPLICATE('2', 255), REPLICATE('3', 256));

此查詢使用未記錄且不受支持的函式sys.fn_RowDumpCracker,並sys.fn_PhyslocCracker顯示有關表的一些有趣細節:

SELECT rdc.*
   , plc.*
FROM dbo.varchartest vct
CROSS APPLY  sys.fn_RowDumpCracker(%%rowdump%%) rdc
CROSS APPLY sys.fn_physlocCracker(%%physloc%%) plc

輸出將與此類似:

╔═════════════════════╦════════════╦═════════╦══════════╦══════════════════════════╦══════════╦═════════════╦═════════════╦═════════╦═════════╦═════════╗
║ partition_id ║ colName ║ IsInrow ║ IsSparse ║ IsRecordPrefixCompressed ║ IsSymbol ║ PrefixBytes ║ InRowLength ║ file_id ║ page_id ║ slot_id ║
╠═════════════════════╬════════════╬═════════╬══════════╬══════════════════════════╬══════════╬═════════════╬═════════════╬═════════╬═════════╬═════════╣
║ 1729382263096344576 ║ varchar30 ║ 1 ║ 0 ║ 0 ║ 0 ║ 0 ║ 30 ║ 1 ║ 1912 ║ 0 ║
║ 1729382263096344576 ║ varchar255 ║ 1 ║ 0 ║ 0 ║ 0 ║ 0 ║ 255 ║ 1 ║ 1912 ║ 0 ║
║ 1729382263096344576 ║ varchar256 ║ 1 ║ 0 ║ 0 ║ 0 ║ 0 ║ 256 ║ 1 ║ 1912 ║ 0 ║
╚═════════════════════╩════════════╩═════════╩══════════╩══════════════════════════╩══════════╩═════════════╩═════════════╩═════════╩═════════╩═════════╝

如您所見,顯示InRowLength了每個值以及每行的物理儲存位置 - “file_id”、“page_id”和“slot_id”。

如果我們從上面的查詢結果中獲取file_id和值並執行它們,我們可以看到實際的物理頁面內容:page_id``DBCC PAGE

DBCC TRACEON (3604); --send display to the client
DBCC PAGE (tempdb, 1, 1912, 3); --database, file_id, page_id, 3 to show page contents
DBCC TRACEOFF (3604);--reset display back to the error log

我機器的結果是:

頁:(1:1912)


緩衝:


BUF @0x00000000FF5B2E80

bpage = 0x0000000024130000 bhash = 0x0000000000000000 bpageno = (1:1912)
bdbid = 2 breferences = 0 bcputicks = 0
bsampleCount = 0 bUse1 = 32497 bstat = 0x10b
部落格 = 0x212121cc bnext = 0x0000000000000000 

頁眉:


頁面@0x0000000024130000

m_pageId = (1:1912) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 98834 m_indexId (AllocUnitId.idInd) = 7936
元數據:AllocUnitId = 2233785421652951040 
元數據:PartitionId = 1945555045333008384 元數據:IndexId = 0
元數據:ObjectId = 34099162 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 4 m_slotCnt = 1 m_freeCnt = 7538
m_freeData = 652 m_reservedCnt = 0 m_lsn = (35:210971:362)
m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = 0 數據庫碎片 ID = 1 

分配狀態

GAM (1:2) = 已分配 SGAM (1:3) = 未分配 PFS (1:1) = 0x41 已分配 50_PCT_FULL
DIFF (1:6) = 未更改 ML (1:7) = 未更改 MIN_LOGGED 

插槽 0 偏移量 0x60 長度 556

記錄類型 = PRIMARY_RECORD 記錄屬性 = NULL_BITMAP VARIABLE_COLUMNS
記錄大小 = 556 
記憶體轉儲@0x000000005145A060

0000000000000000: 30000400 03000003 002d002c 012c0231 31313131 0........-.,.,.11111
0000000000000014: 31313131 31313131 31313131 31313131 31313131 11111111111111111111
0000000000000028: 31313131 31323232 32323232 32323232 32323232 11111222222222222222
000000000000003C: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
0000000000000050: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
0000000000000064: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
0000000000000078: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
000000000000008C: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
00000000000000A0: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
00000000000000B4: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
00000000000000C8: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
00000000000000DC: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
00000000000000F0: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
0000000000000104: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
0000000000000118: 32323232 32323232 32323232 32323232 32323232 22222222222222222222
000000000000012C: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
0000000000000140: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
0000000000000154: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
0000000000000168: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
000000000000017C: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
0000000000000190: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
00000000000001A4: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
00000000000001B8: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
00000000000001CC: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
00000000000001E0: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
00000000000001F4: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
0000000000000208: 33333333 33333333 33333333 33333333 33333333 33333333333333333333
000000000000021C: 33333333 33333333 33333333 33333333 3333333333333333

插槽 0 列 1 偏移量 0xf 長度 30 長度(物理) 30

varchar30 = 11111111111111111111111111111 

插槽 0 列 2 偏移量 0x2d 長度 255 長度(物理) 255

varchar255 = 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222 

插槽 0 列 3 偏移量 0x12c 長度 256 長度(物理) 256

varchar256 = 333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
3333333333333333333333333333333333333333333 

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