Чому б не використовувати varchar (max)?


76

Щодо дизайну баз даних, я трохи старий, тому я повністю використовую правильні розміри даних у стовпцях. Однак, переглядаючи базу даних для свого друга, я помітив, що він varchar(max)багато використовував . Тепер моя безпосередня думка полягала в тому, щоб повернути йому його назад і сказати, щоб він змінив це. Але тоді я задумався і не міг придумати поважної причини, щоб він не використовував його (він використовував інструмент типу case для генерації db, якщо вам цікаво).

Я досліджував тему varchar(max)використання, і я не можу придумати жодної вагомої причини, щоб він не використовував її.

Він не використовує стовпці для індексів, програма, яка знаходиться на базі даних, має обмеження на введення, тому вона не дозволить масивні записи в полях.

Будь-яка допомога буде вдячна, щоб допомогти мені змусити його побачити світло :).


1
Дивіться цю відповідь з іншої причини stackoverflow.com/questions/2009694/…
Мартін Сміт

Це цікаво! Шкода, я не знайшов цього раніше. Дякую!
AtaLoss

5
По-перше: ви не можете розміщувати індекс у VARCHAR(MAX)стовпці ... це одне змушує мене використовувати його лише за крайньої необхідності ....
marc_s

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

Відповіді:


35

Моя відповідь на це - не про використання Макса, а про причину VARCHAR (max) проти TEXT.

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

По-друге, це те, що дозволяють вам робити поля.

ТЕКСТ важко оновити в порівнянні з VARCHAR, але ви отримуєте перевагу повнотекстової індексації та безлічі розумних речей.

З іншого боку, VARCHAR (MAX) має певну неоднозначність, якщо розмір комірки <8000 символів, це буде трактуватися як дані рядка. Якщо воно більше, воно буде розглядатися як LOB для зберігання. Оскільки ви не можете цього знати без запиту RBAR, це може мати стратегії оптимізації для місць, де вам потрібно бути впевненими у своїх даних та скільки це зчитування коштує.

В іншому випадку, якщо ваше використання є відносно буденним, і ви не очікуєте, що у вас виникнуть проблеми з розміром даних (IE, який ви використовуєте .Net, і тому вам не потрібно турбуватися про розмір ваших рядків / символів *) тоді використання VARCHAR (макс.) - це нормально.


4
одне, що я помітив під час читання статей про це, - коли ви запитуєте таблицю, вона повинна буферизувати максимальний розмір запису в пам'яті. так що потенційно це може бути проблемою, але в сучасних середовищах з декількома концертами (якщо не терабайт) і з оперативною пам'яттю дешевою та простою для оновлення, це майже зводить цю проблему нанівець.
AtaLoss

14
Ця відповідь, мабуть, означає, що повнотекстове індексування можна використовувати лише з textтипом даних. Це не так. textє застарілим типом даних і не має переваг перед varchar(max)AFAIK.
Martin Smith

7
Ще однією причиною не використовувати TEXT / NTEXT є те, що вони застаріли.
Аарон Бертран,

1
Чи можете ви це процитувати? Мені було відомо лише про те, що TEXT IN ROW застаріло.
Russ Clarke

1
MSSQL Books Online : типи ntext, text та image будуть видалені в майбутній версії Microsoft SQL Server. Уникайте використання цих типів даних у новій розробці та плануйте модифікувати програми, які їх зараз використовують. Замість цього використовуйте nvarchar (max), varchar (max) та varbinary (max).
tibx

12

Існує повідомлення в блозі про те, чому не використовувати VARCHAR макс тут

Редагувати

Основна відмінність полягає в тому, де зберігаються дані. Рядок даних SQL має максимальний розмір 8000 байт (або він був 8K). Тоді 2 Гб varchar (макс.) Не можна зберігати в рядку даних. SQL Server зберігає його "поза рядом".

Тому ви можете отримати показник продуктивності, оскільки дані не будуть знаходитися в одному місці на диску, див .: http://msdn.microsoft.com/en-us/library/ms189087.aspx


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

1
varchar (max) не буде зберігатися поза рядком, якщо дані, що зберігаються в рядку, не перевищують обмеження рядків (що, так, становить близько 8k). Тобто якщо у вас текст "привіт світ" зберігається у varchar max у таблиці з 3 стовпцями, швидше за все, він не збережеться поза рядком.
AtaLoss

Причина не використовувати їх полягає в тому, що їх неможливо проіндексувати. Поганою практикою є використання nvarchar (max) або varchar (max), якщо ви очікуєте мати дані, які це потребують.
HLGEM

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

2
Показ продуктивності вартий оперативної коректності, коли ви не можете передбачити розмір рядка, який, можливо, вам доведеться вставити в рядок.
binki

2

Якщо ви працюєте в середовищі OLTP, ви все про продуктивність. Від накладних витрат та питань налаштування до обмежень індексації та вузьких місць щодо запитів. Використання varcahr (max) або будь-якого іншого типу LOB, швидше за все, суперечить більшості найкращих практик дизайну, тому, якщо не існує конкретної бізнес-потреби, яку неможливо вирішити за допомогою якогось іншого механізму набору тексту, і лише varchar (max) підходить до Тоді, чому тоді піддавати свою систему та додатки таким накладним витратам та продуктивності, які властиві одному з типів даних LOB?

Якщо, з іншого боку, ви працюєте в середовищі OLAP або в середовищі DW Star Schema із таблицями розмірів із полями дескрипторів, які, природно, повинні бути багатослівними, тоді varchar (max), якщо ви не додаєте це до індексу, може бути корисним. Проте я б рекомендував навіть тоді використовувати char (x) varchar (x), оскільки завжди найкращою практикою є використання лише тих ресурсів, які обов’язково повинні бути для виконання роботи.


1

Їх НЕ слід використовувати, якщо ви не очікуєте великих обсягів даних, і ось причина (безпосередньо від Books Online):

Стовпці, що мають типи даних великого об'єкта (LOB), ntext, text, varchar (max), nvarchar (max), varbinary (max), xml або image не можна вказати як ключові стовпці для індексу.

Якщо ви хочете скалічити продуктивність, використовуйте nvarchar для всього.


2
Але що, якщо ти ніколи не збираєшся натискати цю колонку? Якщо ви зберігаєте крапку тексту, ви, мабуть, шукаєте його за іншим стовпцем клавіш. У чому полягає така велика стурбованість необхідністю розміщення індексів у стовпцях, які, ймовірно, зберігатимуть текст вільної форми і ніколи не з’являтимуться, WHEREкрім, можливо, для перевірки IS NULL?
binki

@binki, порада не використовувати varchar (max) для всього, оскільки там будуть поля, які потрібно проіндексувати. Він призначений лише тоді, коли вам потрібні великі обсяги даних.
HLGEM

1
Просто те, що це з Інтернет-книги, не означає, що це правильно :) Ще один приклад інколи правильного використання (MAX) - це коли ви зберігаєте рядки з джерела (наприклад, великі крапки, поля NOSQL), яке не має розміру, тож ви цього не робите ' я не знаю, наскільки це може бути. І я погоджуюсь з @binki, часто є стовпці, які, як ви знаєте, ніколи не проіндексуєте.
сорок,

1

Про це Redgate написав чудову статтю.
https://www.red-gate.com/simple-talk/sql/database-administration/whats-the-point-of-using-varcharn-anymore/

Висновки

  • Там, де це доречно, використовуйте VARCHAR (n) над VARCHAR (MAX) з міркувань гарного дизайну, якщо не переваги продуктивності, а також тому, що дані VARCHAR (MAX) не стискаються
  • Зберігання великих рядків займає більше часу, ніж зберігання маленьких рядків.
  • Оновлення значення рядка VARCHAR (MAX) від 8000 до понад 8000 буде відносно повільним, але різниця для однієї транзакції, швидше за все, не буде вимірюваною.
  • Оновлення значення рядка VARCHAR (MAX) з понад 8000 до нижче 8000 буде швидшим, ніж якщо таблиця встановлена ​​для зберігання даних поза рядком.
  • Використання позарядкової опції для VARCHAR (MAX) спричинить повільнішу запис, поки рядки не стануть дуже довгими.

0

Я не знаю, як сервер sql обробляє великі (задекларовані) поля varchar з точки зору продуктивності, пам'яті та сховища .. але якщо припустити, що це робиться так само ефективно, як і менші задекларовані поля varchar, все ще існує перевага обмежень цілісності.

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


Це хороший момент, особливо якщо ви не використовуєте керовану мову для читання своїх рядків.
Русс Кларк,

Це хороший момент. Я згадаю це, це розробляється в c # 3.5 або 4 (я вважаю, я повинен запитати його).
AtaLoss


@RussClarke Чи справді рядки змінної довжини - це керована річ? Здається, ви ніколи не стикалися з розподілом купи у некерованих середовищах :-p.
binki

@MartinSmith Це дуже незначні покращення продуктивності. Крім того, блогер використовує VARCHAR(MAX)порівняння та в WHEREпункті. Я б розраховував на VARCHAR(MAX)те, що ви б не порівнювали або WHEREв SQL - наприклад, blob вмісту допису в блозі, текстовий опис чогось у вільній формі. Якщо ви хочете порівняти або WHERE, тоді, звичайно, допоможе обмеження. Його приклад 'abc'можна навіть перевести у порівняння двох цілих чисел. Це не той тип даних, який можна VARCHAR(MAX)
вводити

0

Різниця в наступному:
VARCHAR(X)можна індексувати та зберігати у MDF/NDFфайлі даних.
VARCHAR(MAX)неможливо проіндексувати, оскільки може досягати великого обсягу, а потім зберігатиметься як відокремлений файл, а не у MDF/NDFфайлі даних.


6
Як ви думаєте, де саме MS SQL зберігає дані LOB, як не у файлах .mdf?

0

   Дещо старомодно вважати, що програма передаватиме лише короткі рядки до бази даних, і це зробить це нормально .

   У наш час ти МАЄШ передбачити, що до бази даних буде отримувати доступ переважно поточна програма, але може існувати майбутня версія програми ((чи знатиме розробник цієї версії тримати рядки менше певної довжини?)

   Ви ПОВИННІ передбачити, що веб-служби, процеси ETL, LYNC to SQL та будь-яка інша кількість вже існуючих та / або ще не існуючих технологій будуть використані для доступу до вашої бази даних.

   Взагалі кажучи, я намагаюся не переходити через varchar (4000), адже це , зрештою , чотири тисячі символів . Якщо я перевищую це значення, тоді я звертаюся до інших типів даних, щоб зберегти все, що я намагаюся зберегти. Брент Озар написав про це досить чудові речі .

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.