чи є перевага varchar (500) перед varchar (8000)?


90

Я читав це на форумах MSDN і тут, і досі мені незрозуміло. Я вважаю, що це правильно: Varchar (max) буде зберігатися як текстовий тип даних, що має недоліки. Тож припустимо, ваше поле надійно матиме менше 8000 символів. Як поле BusinessName у моїй таблиці бази даних. Насправді, назва компанії, мабуть, завжди буде мати менше 500 символів (витягуючи число з мого капелюха). Здається, що безліч полів varchar, які я перебігаю, потрапляють далеко під 8 тисяч символів.

То чи повинен я зробити це поле varchar (500) замість varchar (8000)? З того, що я розумію в SQL, між ними немає різниці. Отже, щоб полегшити життя, я хотів би визначити всі свої поля varchar як varchar (8000). Чи є у цього якісь недоліки?

Пов’язане: Розмір стовпців varchar (я не відчував, що цей відповів на моє запитання).


6
Уявіть, що ви намагаєтесь розмістити на візитній картці назву компанії довжиною 500 символів ... :)
OMG Ponies

2
@OMG Поні: кожного разу, коли я бачу ваше ім’я користувача, я хихочу. Що ти говорив? (
Жартую

4
@jcollum: SpaceMan Spiff завжди отримає мій голос. Це неправда - підійдуть будь-які Calvin & Hobbes, але особливо ті, що ліплять сніг. Або тиранозавр, що летить на F-14. Але я відступаю ...
OMG Ponies

Відповіді:


20

З точки зору обробки, не буде різниці використання varchar (8000) проти varchar (500). Це швидше "хороша практика", щоб визначити максимальну довжину, яку повинно містити поле, і зробити ваш varchar такою довжиною. Це те, що може бути використано для сприяння валідації даних. Наприклад, зробити абревіатуру штату 2 символами або поштовий / поштовий індекс 5 або 9 символами. Раніше це було більш важливою відмінністю, коли ваші дані взаємодіяли з іншими системами або користувальницькими інтерфейсами, де довжина поля була критичною (наприклад, набір даних плоского файлу мейнфрейма), але сьогодні я думаю, що це більше звичка, ніж будь-що інше.


3
Має сенс ... щодо речей, які, природно, мають максимальну довжину. Але що робити, коли максимальна довжина не очевидна? Наприклад, назва компанії.
jcollum

2
Для чогось подібного, якщо я не передбачаю жодного способу прогнозувати розмір, який потенційно може бути, тоді я зазвичай буду використовувати varchar (8000) або varchar (max), залежно від типу даних
BBlake

4
Здається, це робить різницю в продуктивності навіть у 2017 році: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name

1
Пізніші відповіді показують , що є витрати: це впливає оптимізація логічного відповіді Мартіна Сміта , а також розглянути 8К загальні питання розміру рядка , згадані ГБН і Олівер .
ToolmakerSteve

124

Одним із прикладів, коли це може змінити ситуацію, є те, що це може запобігти оптимізації продуктивності, яка дозволяє уникнути додавання інформації про версії рядків до таблиць із тригерами після.

Тут висвітлено SQL Kiwi

Фактичний розмір збережених даних несуттєвий - важливий саме потенційний розмір.

Подібним чином, якщо з 2016 року використовуються таблиці, оптимізовані для пам'яті, можна використовувати стовпці LOB або комбінації ширини стовпців, які потенційно можуть перевищувати обмеження вростання, але із штрафом.

(Макс.) Стовпці завжди зберігаються поза рядами. Для інших стовпців, якщо розмір рядка даних у визначенні таблиці може перевищувати 8 060 байт, SQL Server витісняє найбільші стовпці змінної довжини поза рядками. Знову ж таки, це не залежить від кількості даних, які ви там зберігаєте.

Це може мати великий негативний вплив на споживання пам'яті та продуктивність

Інший випадок, коли надмірна декларація ширини стовпців може мати велике значення, - якщо таблиця коли-небудь буде оброблена за допомогою SSIS. Пам'ять, виділена для стовпців змінної довжини (не BLOB), фіксується для кожного рядка у дереві виконання і відповідає заявленій максимальній довжині стовпців, що може призвести до неефективного використання буферів пам'яті (приклад) . Хоча розробник пакета SSIS може оголосити менший розмір стовпця, ніж джерело, цей аналіз найкраще робити заздалегідь і застосовувати там.

Повертаючись до самого механізму SQL Server, схожий випадок полягає в тому, що при обчисленні дози пам'яті для виділення SORTоперацій SQL Server припускає, що varchar(x)стовпці в середньому споживають x/2байти.

Якщо більшість ваших varcharстовпців заповнені, це може призвести до sortпереливання операцій tempdb.

У вашому випадку, якщо ваші varcharстовпці оголошені як 8000байти, але насправді мають вміст набагато менше, ніж для вашого запиту буде виділено пам'ять, яка йому не потрібна, що, очевидно, неефективно і може призвести до очікування надання грантів.

Це висвітлено у Частині 2 веб-трансляції SQL Workshop 1, яку можна завантажити звідси або див. Нижче.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Знімок екрана

SELECT id,name8000
FROM T
ORDER BY number

Знімок екрана


1
отже, якщо майже всі мої значення складають 3 або 4 символи, не можуть перевищувати 4 символи коли-небудь, і я хочу уникнути "операцій сортування, що переливаються в tempdb", я оголошу свою колонку VARCHAR (8) і використовую обмеження CHECK для забезпечення цього стовпця ширина не може перевищувати 4 символів. Що ти думаєш?
AK

12
@AlexKuznetsov - У цій ситуації я б оголосив їх такими, що char(4)в будь-якому випадку на кожен стовпець змінної припадає 2 байти.
Martin Smith

9

Окрім найкращих практик (відповідь BBlake)

  • Ви отримуєте попередження про максимальний розмір рядка (8060) байт та ширину індексу (900 байт) з DDL
  • DML загине, якщо ви перевищите ці межі
  • ANSI PADDING ON є типовим, щоб ви могли в кінцевому підсумку зберігати ціле пробіл

38
Тільки для уточнення щодо ANSI PADDING ON: при використанні nvarcharта varcharтипах це означає лише те, що кінцеві пробіли зберігаються при вставці, а не те, що значення заповнюються пробілами до розміру стовпця, як у charта nchar.
Ben M

9

Є великі недоліки великих стовпців, які є трохи менш очевидними і можуть виявити вас трохи пізніше:

  • Усі стовпці, які ви використовуєте в INDEX - не повинні перевищувати 900 байт
  • Усі стовпці в реченні ORDER BY не можуть перевищувати 8060 байт. Це трохи важко зрозуміти, оскільки це стосується лише деяких стовпців. Детальніше див. У статті « Перевищено обмеження розміру рядка SQL 2008 R2» )
  • Якщо загальний розмір рядка перевищує 8060 байт, ви отримуєте " розлив сторінки " для цього рядка. Це може вплинути на продуктивність (Сторінка є одиницею розподілу в SQLServer і фіксується в 8000 байт + деякі накладні витрати. Перевищення цього не буде серйозним, але це помітно, і ви повинні намагатися уникати цього, якщо вам це легко вдається)
  • Багато інших внутрішніх структур даних, буфери та, що не менш важливо, ваші власні змінні та табличні змінні - всі вони повинні відображати ці розміри. При надмірних розмірах надмірне виділення пам'яті може вплинути на продуктивність

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

У вашому прикладі назв компаній подумайте, де ви можете їх відобразити. Невже є місце для 500 символів ?? Якщо ні, то зберігати їх як такі мало сенсу. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States перелічує деякі назви компаній, і максимум складає близько 50 символів. Тож я б використав 100 для макс. Стовпця Можливо, більше як 80.


2

В ідеалі, ви хотіли б зменшити менше, ніж до розумної довжини (500 не має достатнього розміру) і переконатися, що перевірка клієнта ловить, коли дані будуть занадто великими, і надсилає корисну помилку.

Хоча varchar насправді не збирається зарезервувати простір у базі даних для невикористаного місця, я згадую версії SQL Server, які мають snit про рядки бази даних, ширші за деяку кількість байтів (не згадують точну кількість) і фактично викидають які б дані не підходили. Певна кількість цих байтів була зарезервована для речей, внутрішніх для SQL Server.


правда, раніше це також було набагато більшим занепокоєнням. Але в наш час космос дійсно дешевий, тому я не думаю, що це викликає велике занепокоєння, принаймні з моєї точки зору.
BBlake

1
@jcollum: У вашому прикладі 500, здається, не мають достатнього розміру для назви компанії.
Отіс

1
@BBlake: Незалежно від вартості сховища, якщо SQL Server все ще має обмеження на розмір рядків, то не має значення, скільки місця у вас є. Ви можете зберігати все в текстових блоках, але є деякі SQL-операції, які ви не можете зробити на великій крапці, ніж на varchar.
Отіс

2
@Otis: я хочу сказати наступне: немає фактичного обмеження на розмір назви компанії. Якщо десь не існує закону. Тож у такому випадку я б зробив це поле varchar (8000) і називав би його днем. Моє мислення йде так: Справжнє обмеження? varchar (x). Немає реальних обмежень? varchar (8000).
jcollum

24
Я думав, що близько 30 символів добре для назв міст, поки не побачив Ель Пуебло де Нуестра Сеньора ла Рейна де лос Анхелес дель Ріо де Порчункула
StuartLC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.