Найкращі практики щодо довжини стовпців вархара SQL [закрито]


290

Кожного разу, коли встановлюється нова таблиця SQL або додається новий varcharстовпець до вже наявної таблиці, мені цікаво одне: яке найкраще значення для length.

Отже, скажімо, у вас є стовпець, який називається nameтипу varchar. Отже, ви повинні вибрати довжину. Я не можу придумати ім'я> 20 символів, але ти ніколи не дізнаєшся. Але замість того, щоб використовувати 20, я завжди округляю до наступного 2 ^ n числа. У цьому випадку я вибрав би 32 як довжину. Я це роблю, тому що, з точки зору комп'ютерного вченого, число 2 ^ n виглядає evenдля мене більше, ніж інші числа, і я просто припускаю, що архітектура під ним може обробляти ці числа трохи краще, ніж інші.

З іншого боку, наприклад, MSSQL-сервер встановлює значення довжини за замовчуванням на 50, коли ви вирішите створити колону varchar. Це змушує мене думати про це. Чому 50? це просто випадкове число, або на основі середньої довжини стовпця, або що?

Можливо, можливо, що різні реалізації SQL-серверів (як MySQL, MSSQL, Postgres, ...) мають різні найкращі значення довжини стовпців.

Відповіді:


238

Немає СУБД я НЕ знаю мають яку - або «оптимізацію» , які зроблять VARCHARз 2^nдовжиною краще , ніж один з maxдовжиною, яка не є ступенем 2.

Я думаю, що ранні версії SQL Server насправді розглядали VARCHARдовжину 255 інакше, ніж одну з більшою максимальною довжиною. Я не знаю, чи все ще так.

Практично для всіх СУБД фактична необхідна пам’ять визначається лише кількістю символів, які ви вводите в неї, а не maxдовжиною, яку ви визначаєте. Отже, з точки зору пам’яті (а також, швидше за все, і продуктивності), це не має ніякої різниці, оголошуєте ви стовпець як VARCHAR(100)або VARCHAR(500).

Ви повинні бачити maxдовжину VARCHARстовпця як певне обмеження (або ділове правило), а не технічну / фізичну річ.

Для PostgreSQL найкращою настройкою є використання textбез обмеження довжини та CHECK CONSTRAINTобмеження кількості символів на те, що потрібно вашому бізнесу.

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

Те саме можна застосувати і для Oracle та інших - в Oracle це було б VARCHAR(4000)замість цього text.

Я не знаю, чи є фізична різниця між сховищами VARCHAR(max)і, наприклад, VARCHAR(500)у SQL Server. Але, мабуть, є ефективність роботи при використанні varchar(max)в порівнянні з varchar(8000).

Дивіться це посилання (опублікував Ервін Брандштеттер як коментар)

Редагувати 22.09.2013

Щодо коментаря коханого:

У Postgres версії до 9.2 (яка не були доступні , коли я писав початковий відповідь) зміна в визначення стовпчика було переписати всю таблицю, дивіться , наприклад , тут . З 9.2 цього вже не так, і швидкий тест підтвердив, що збільшення розміру стовпця для таблиці на 1,2 мільйона рядків дійсно зайняло лише 0,5 секунди.

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

Для MySQL в посібнику написано: " У більшості випадків ALTER TABLEробиться тимчасова копія оригінальної таблиці ". І мої власні тести підтверджують, що: запуск ALTER TABLEтаблиці на 1,2 мільйона рядків (те саме, що і в моєму тесті з Postgres) для збільшення розміру стовпця зайняв 1,5 хвилини. У MySQL, однак, ви не можете використовувати "вирішення", щоб використовувати обмеження для обмеження кількості символів у стовпці.

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

Редагувати 2017-01-24

Здається, я (принаймні частково) помилявся щодо SQL Server. Дивіться цю відповідь від Аарона Бертран, яка показує, що оголошена довжина а nvarcharабо varcharстовпців робить величезну різницю для продуктивності.


34
Власне, існує різниця між VARCHAR (255) і VARCHAR (500), навіть якщо ви помістите 1 символ у такий стовпець. Значення, додане в кінці рядка, буде цілим числом, яке зберігає фактичну довжину збережених даних. У випадку VARCHAR (255) це буде 1 байт цілого числа. У випадку VARCHAR (500) це буде 2 байти. це невелика різниця, але варто пам’ятати про це. У мене немає даних про те, як це може вплинути на продуктивність, але я припускаю, що це настільки мало, що досліджувати не варто.
NB

1
@NB: саме так я мав на увазі значення "258" SQL Server "255". Дякуємо за роз’яснення.
a_horse_with_no_name

4
@NB До якого RDBMS ви звертаєтесь? SQL Server? Є вплив на продуктивність. [N] VARCHAR (макс.) Працює трохи повільніше, ніж [N] VARCHAR (n). Мене нещодавно відсилали на цей сайт . Те саме не стосується PostgreSQL для всіх, що я знаю.
Erwin Brandstetter

@ErwinBrandstetter: Дякую за посилання. Схоже, varchar(max)це, мабуть, більше схоже на OracleCLOB
a_horse_with_no_name

1
Зміна довжини вархара не переписує таблицю. Він просто перевіряє довжину обмеження щодо всієї таблиці точно так само, як ЗАВЕРШИТИ БЕЗКОШТОВНО. Якщо ви збільшуєте довжину, нічого не робити, просто наступна вставка або оновлення приймуть більшу довжину. Якщо ви зменшите довжину, і всі рядки пройдуть нове менше обмеження, Pg не вживатиме жодних подальших дій, крім того, щоб дозволити наступним вставкам або оновленням писати лише нову довжину.
Маньєро

70

VARCHAR(255)і VARCHAR(2)займайте рівно стільки ж місця на диску! Тож єдина причина, щоб обмежити це, якщо у вас є конкретні потреби, щоб він був меншим. Інакше зробіть їх усіх 255.

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

Дивіться: Які оптимальні розміри варшарів для MySQL?


7
Чому б не зробити їх усіма VARCHAR(MAX)? Простір - не єдине врахування при моделюванні бази даних. Домен, який ви моделюєте, повинен визначати типи даних та розміри.
Одід

6
@Oded VARCHAR(MAX)- це не те саме, що varchar(255)або varchar(65535)- varchar max - тип типу textданих. І на ваш погляд - якби він знав, що таке "домен, який він моделює", він би не ставив цього питання. Очевидно, він не знає, наскільки великі будуть його дані, і я запевняю його, що зробити його в повному розмірі нічого не шкодить.
Аріель

4
@Ariel: Існують проблеми та обмеження щодо індексів. Ви не можете мати (a,b,c,d)індекс, коли всі чотири стовпці VARCHAR(255).
ypercubeᵀᴹ

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

Я думаю, якщо ми знаємо точне значення, я вважаю за краще використовувати char. Тим часом, якщо це все ще передбачається, я використовую varchar і зберігаю 255, оскільки це динамічний розподіл пам'яті, щоб ви не турбувалися про розмір, який буде прийнято
Faris Rayhan

54

Кожного разу, коли я встановлюю нову таблицю SQL, я відчуваю те саме, що 2 ^ n є більш "рівним" ... але підсумовуючи відповіді тут, немає значного впливу на місце зберігання, просто визначаючи varchar (2 ^ n) або навіть варчар (MAX).

З огляду на це, ви все ще повинні передбачити потенційні наслідки для зберігання та продуктивності при встановленні високого ліміту varchar (). Наприклад, скажімо, ви створюєте стовпець varchar (MAX) для зберігання описів продуктів із повнотекстовою індексуванням. Якщо 99% описів мають довжину всього 500 символів, а потім раптом ви знайдете когось, хто замінює описані описи статтями у Вікіпедії, ви можете помітити непередбачені значні хіти для зберігання та продуктивності.

Ще одна річ, яку слід врахувати у Білла Карвіна :

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

По суті, просто придумайте розумні обмеження та помилки щодо дещо більшого розміру. Як зазначав @onedaywhen, прізвища у Великобританії зазвичай складають від 1-35 символів. Якщо ви вирішите зробити це varchar (64), вам насправді нічого не зашкодить ... якщо тільки ви не зберігаєте прізвище цього хлопця, яке, як кажуть, має довжину до 666 символів. У цьому випадку, можливо, варчар (1028) має більше сенсу.

І якщо це корисно, ось як може виглядати варчар 2 ^ 5 до 2 ^ 10, якби він був заповнений:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

Найкраще значення - це те, що підходить для даних, визначених у нижньому домені.

Для деяких доменів VARCHAR(10)це Nameатрибут є правильним , а для інших VARCHAR(255)- найкращим вибором.


15

Додавши до відповіді a_horse_with_no_name, ви можете виявити наступне, що цікавить ...

це не має ніякої різниці, оголошуєте ви стовпець як VARCHAR (100) або VACHAR (500).

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Не забувайте про довжину байтів (байтів) і нульовий байт таким чином:

name varchar(100) not null становитиме 1 байт (довжина) + до 100 символів (latin1)

name varchar(500) not null буде 2 байти (довжина) + до 500 символів (latin1)

name varchar(65533) not null буде 2 байти (довжина) + до 65533 символів (latin1)

name varchar(65532) становитиме 2 байти (довжина) + до 65532 символів (latin1) + 1 нульовий байт

Сподіваюся, це допомагає :)


Ви використовуєте MySQL, а питання про MSSQL
Богдан Март

6

Завжди звертайтеся до експерта з домену бізнесу. Якщо це ти, шукай галузевий стандарт. Наприклад, якщо домен, про який йдеться, - прізвище (прізвище) фізичної особи, то для британського бізнесу я б зайшов до каталогу стандартів даних Великобританії Govtalk для отримання інформації про особу та виявив, що прізвище матиме від 1 до 35 символів .


3

Я не перевіряв цього останнім часом, але в минулому з Oracle я знаю, що драйвер JDBC резервував шматок пам'яті під час виконання запиту, щоб утримати результат набору, який повертається. Розмір фрагмента пам'яті залежить від визначень стовпців та розміру вибору. Отже, довжина стовпців varchar2 впливає на те, скільки пам'яті зарезервовано. Це викликало серйозні проблеми з роботою для мене років тому, тому що ми завжди використовували varchar2 (4000) (максимум на той час), а збирання сміття було набагато менш ефективним, ніж сьогодні.


-2

У певному сенсі ви праві, хоча все, що нижче 2 ^ 8 символів, все одно буде зареєстровано як байт даних.

Якщо ви враховуєте базовий символ, який залишає що-небудь з VARCHAR <255, як витрачає стільки ж місця.

255 є хорошим базовим визначенням, якщо ви особливо не хочете зменшити надмірне введення.


" хоча все, що нижче 2 ^ 8 символів, все одно буде зареєстровано як байт даних " - неправильно. У базі даних зберігається лише стільки символів, скільки передбачено у форматі VARCHAR. Жодний пробіл не "зареєстрований", зарезервований або ініціалізований при оголошенні стовпця.
a_horse_with_no_name
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.