Розмістіть кожен стовпчик відповідно. НЕ використовуйте "стандартний" розмір для кожного стовпця. Якщо вам потрібно лише 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 ║ IsRecordPrefixCompression ║ IsSymbol ║ ПрефіксBytes ║ 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 значень = 0 bcputicks = 0
bsampleCount = 0 bUse1 = 32497 bstat = 0x10b
blog = 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 Ідентифікатор фрагмента БД = 1
Статус розподілу
GAM (1: 2) = ALLOCATED SGAM (1: 3) = NOT ALLOCATED PFS (1: 1) = 0x41 ALLOCATED 50_PCT_FULL
DIFF (1: 6) = НЕ ЗМЕНЕНО ML (1: 7) = НЕ МІНЬОГОЛОГІЧЕНО
Слот 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 1111111111111111111111
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 333333333333333333
Слот 0 Стовпчик 1 Зсув 0xf Довжина 30 Довжина (фізична) 30
varchar30 = 11111111111111111111111111111111
Слот 0 Колонка 2 Зсув 0x2d Довжина 255 Довжина (фізична) 255
varchar255 = 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
22222222222222222222222222222222222222222222
Слот 0 Стовпчик 3 Зсув 0х12с Довжина 256 Довжина (фізична) 256
varchar256 = 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
3333333333333333333333333333333333333333333