varchar (макс.) скрізь?


81

Чи є якісь проблеми з перетворенням усіх ваших рядків Sql Server 2008 на стовпці varchar (max)? Мої допустимі розміри рядків управляються додатком. База даних повинна просто зберігати те, що я їй даю. Чи прийму я показник продуктивності, оголосивши всі стовпці рядків типом varchar (max) у Sql Server 2008, незалежно від розміру даних, які насправді потрапляють у них?


1
Під час мого читання це звучить так, ніби стовпці varchar сервера Sql Server "автоматично збільшуються". Тож чи не може стовпець varchar (max), де максимальна довжина будь-якого заданого значення 20, однаковий із стовпцем varchar (20)?
BowserKingKoopa

Відповіді:


49

За допомогою VARCHAR(MAX)ви в основному говорите SQL Server "зберігати значення в цьому полі, як вам найкраще бачиться", тоді SQL Server вирішить, чи слід зберігати значення як звичайні VARCHARчи як LOB (великий об'єкт). Загалом, якщо збережені значення менше 8000 байт, SQL Server буде розглядати значення як звичайний VARCHARтип.

Якщо значення, які зберігаються, занадто великі, то стовпець може виливати сторінку на сторінки LOB, точно так, як це робиться для інших типів LOB ( text, ntextі image) - якщо це трапляється, для зчитування даних, що зберігаються в на додаткових сторінках (тобто існує певна продуктивність), однак це відбувається лише в тому випадку, якщо збережені значення занадто великі .

Насправді в рамках SQL Server 2008 або пізнішої версії дані можуть переливатися на додаткові сторінки, навіть із фіксованою довжиною типів даних (наприклад VARCHAR(3,000)), однак ці сторінки називаються сторінками даних із переповненням рядків і трактуються дещо інакше.

Коротка версія: з точки зору зберігання немає недоліків використання VARCHAR(MAX)більш VARCHAR(N)для деяких N.

(Зверніть увагу, що це також стосується інших типів полів змінної довжини NVARCHARта VARBINARY)

FYI - Ви не можете створювати індекси в VARCHAR(MAX)стовпцях


Це може бути справедливим лише для полів, що допускають обнулення. Кожен ненульовий стовпець varchar (макс.) Або nvarchar (макс.) Вимагає 24 байт додаткового фіксованого розподілу. docs.microsoft.com/en-us/sql/t-sql/data-types/…
Liazy,

34

Індекси не можуть перевищувати 900 байт для одного. Отже, ви ніколи не можете створити індекс. Якщо ваші дані менше 900 байт, використовуйте varchar (900).

Це один мінус: адже це дає

  • дуже погана продуктивність пошуку
  • відсутність унікальних обмежень

Але що, якщо стовпець varchar (max) не має значень, що перевищують 900 байт? Чи було б це тоді індексувати? Я розгублений, тому що багато з того, що я читаю, змушують типи стовпців varchar звучати так, ніби вони автоматично встановлюють розмір до максимального значення при введенні даних. Це було б ідеально підходить для того, що я хочу, тому що саме додаток повинен визначати максимум, а не база даних.
BowserKingKoopa

3
Ви отримаєте попередження під час створення індексу та помилку при спробі вставити> 900. Але якщо ваші дані завжди <900, чому б не використовувати 900? Так, вони зберігаються як рядки змінної довжини.
gbn

8
Я не знаю, чи завжди мої дані мають значення <900. Це проблема бізнес-логіки. Якщо це правило зміниться, я повинен змінити його в бізнес-логіці. Мені не потрібно також міняти базу даних. Це моя мета в будь-якому випадку. Щоб побачити, чи зможу я уникнути проблеми з розмірами рядків, не помічаючи значної продуктивності.
BowserKingKoopa

2
Як часто корисно індексувати довгий текстовий стовпець? Навіть варто було б індексувати щось на зразок стовпця varchar (200)? Зрештою, сам індекс був би неефективним. Необхідність пошуку за довгими "точними збігами" здається малоймовірною. І пошук шаблонів був би корисним лише в тому випадку, якщо відомий початок шаблону.
Розчарований

9

Саймон Сабін писав пост про це деякий час тому. У мене немає часу, щоб захопити його зараз, але вам слід його шукати, тому що він приходить до висновку, що ви не повинні використовувати varchar (max) за замовчуванням.

Відредаговано: Саймон отримав кілька публікацій про varchar (max). Посилання в коментарях нижче це досить добре показують. Я думаю, що найбільш значущим є http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx , де йдеться про ефект varchar (макс.) на кешуванні плану. Загальний принцип - бути обережним. Якщо вам не потрібно, щоб він був максимальним, тоді не використовуйте max - якщо вам потрібно більше 8000 символів, то, звичайно ... йдіть на це.




Перший. Автор: OMG Ponies.
Роб Фарлі

На жаль, я не встиг знайти фактичне посилання, я збирався вступити на зустріч, коли хотів звільнити відповідь.
Роб Фарлі

1
І що більш важливо, цей: sqlblogcasts.com/blogs/simons/archive/2009/07/11/…
Роб Фарлі

6

Щодо цього питання конкретно кілька пунктів, яких я не бачу, згадуються.

  1. На 2005/2008/2008 R2, якщо стовпець LOB буде включений до індексу, це заблокує перебудову індексу в Інтернеті.
  2. З 2012 року обмеження відновлення індексу в Інтернеті скасовано, але стовпці LOB не можуть брати участь у новій функціональності Додавання NOT NULL стовпців в якості інтернет - операції .
  3. Блокування можна довше витягувати з рядків, що містять стовпці цього типу даних. ( більше )

Кілька інших причин висвітлюються у моїй відповіді, чому не varchar(8000)скрізь .

  1. Ваші запити можуть в кінцевому підсумку запитувати величезні обсяги пам’яті, не виправдані розміром даних.
  2. У таблиці з тригерами це може запобігти оптимізації, коли теги версій не додаються.

5

Подібне питання я задавав раніше. отримав кілька цікавих відповідей. Перевір тут Був один сайт, на якому хлопець говорив про шкоду використання широких стовпців, однак якщо ваші дані обмежені в додатку, моє тестування спростувало це. Той факт, що ви не можете створювати індекси на стовпцях, означає, що я б їх не використовував постійно (особисто я б їх не використовував так багато взагалі, але я трохи пурист у цьому плані). Однак якщо ви знаєте, що в них небагато зберігається, я не думаю, що вони такі погані. Якщо ви виконуєте сортування на стовпцях набору записів із варчаром (макс.) (Або будь-яким широким стовпцем, що є символом чи варчаром), тоді ви можете зазнати покарання за продуктивність. вони можуть бути вирішені (якщо потрібно) індексами, але ви не можете розміщувати індекси на varchar (max). Якщо ви хочете в майбутньому перевірити свої стовпці, чому б просто не помістити їх у щось розумне. наприклад, стовпець імені повинен містити 255 символів замість max ...


2

Є ще одна причина уникати використання varchar (max) у всіх стовпцях. З тієї ж причини, що ми використовуємо обмеження перевірки (щоб уникнути заповнення таблиць непотрібною програмою, спричиненою помилковим програмним забезпеченням або записами користувачів), ми хотіли б захиститися від будь-якого несправного процесу, який додає набагато більше даних, ніж передбачалося. Наприклад, якщо хтось чи щось намагається додати 3000 байт у поле City, ми точно знаємо, що щось не так, і хочемо зупинити процес мертвим, щоб налагодити його якомога раніше. Ми також знали б, що назва міста містом у 3000 байт не могла бути дійсною і зіпсувала звіти та таке інше, якби ми намагалися його використовувати.


1

В ідеалі, ви повинні дозволяти лише те, що вам потрібно. Це означає, що якщо ви впевнені, що певний стовпець (скажімо, стовпець з іменем користувача) ніколи не буде довшим більше 20 символів, використання VARCHAR (20) проти VARCHAR (MAX) дозволяє базі даних оптимізувати запити та структури даних.

З MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

Ви дійсно коли-небудь збираєтесь наблизитися до 2 ^ 31-1 байт для цих стовпців?


3
Я не вважаю правильним характеризувати це як "розподіл". БД насправді ніде не резервує вам 2 ^ 31-1 байт.
Скотт Стаффорд,

1
"стовпець імені користувача [..] ніколи не буде мати більше 20 символів" - Чудово, поки одного дня клієнт не вирішить, що потрібно довше. Ми всі були там. :)
Стів Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.