Лучшие практики для длины столбца SQL varchar [закрыто]


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).

Смотрите эту ссылку (опубликовано Erwin Brandstetter в качестве комментария)

Изменить 2013-09-22

Что касается комментария Bigown:

В 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: это то, что я имел в виду для «магического» значения SQL Server 255. Спасибо за разъяснения.
a_horse_with_no_name

4
@NB К какой РСУБД вы обращаетесь? SQL Server? Это влияет на производительность. [N] VARCHAR (макс.) Работает немного медленнее, чем [N] VARCHAR (n). Меня недавно перевели на этот сайт . То же самое не относится к PostgreSQL, насколько я знаю.
Эрвин Брандштеттер

@ErwinBrandstetter: Спасибо за ссылку. Похоже, varchar(max)это больше похоже на OracleCLOB
a_horse_with_no_name

1
Изменение длины varchar не переписывает таблицу. Он просто проверяет длину ограничения для всей таблицы в точности как CHECK CONSTRAINT. Если вы увеличиваете длину, ничего не поделаешь, просто следующая вставка или обновления примут большую длину. Если вы уменьшаете длину, и все строки проходят новое меньшее ограничение, Pg не предпринимает никаких дальнейших действий, кроме того, чтобы позволить следующим вставкам или обновлениям записывать только новую длину.
Маньеро

70

VARCHAR(255)и VARCHAR(2)занять ровно столько же места на диске! Таким образом, единственная причина ограничить это, если у вас есть конкретная потребность, чтобы он был меньше. В противном случае сделайте их всех 255.

В частности, при выполнении сортировки столбцы большего размера занимают больше места, поэтому, если это ухудшает производительность, вам нужно беспокоиться об этом и уменьшать их. Но если вы выберете только одну строку из этой таблицы, вы можете просто сделать их все 255, и это не будет иметь значения.

Смотрите: Каковы оптимальные размеры varchar для 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, поскольку это динамическое распределение памяти, поэтому вы не должны беспокоиться о размере, который будет взят
Фарис Райхан

54

Всякий раз, когда я настраиваю новую таблицу SQL, я чувствую то же самое, когда 2 ^ n более "четный" ... но, суммируя ответы здесь, нет существенного влияния на пространство хранения, если просто определить varchar (2 ^ n) или даже varchar (Макс).

Тем не менее, вы все равно должны предвидеть потенциальные последствия для хранения и производительности при установке высокого предела varchar (). Например, допустим, вы создали столбец varchar (MAX) для хранения описаний продуктов с полнотекстовой индексацией. Если длина 99% описаний составляет всего 500 символов, а затем вдруг появляется кто-то, кто заменяет упомянутые описания статьями в Википедии, вы можете заметить непредвиденные значительные потери памяти и производительности.

Еще одна вещь от Билла Карвина :

Есть одно возможное влияние на производительность: в MySQL временные таблицы и таблицы MEMORY хранят столбец VARCHAR в виде столбца фиксированной длины, дополненного его максимальной длиной. Если вы разрабатываете столбцы VARCHAR, размер которых значительно превышает необходимый вам размер, вы будете использовать больше памяти, чем нужно. Это влияет на эффективность кэша, скорость сортировки и т. Д.

В основном, просто придумайте разумные бизнес-ограничения и ошибки немного большего размера. Как отметил @onedaywhen, фамилии в Великобритании обычно составляют от 1 до 35 символов. Если вы решите сделать его varchar (64), вы не причините вреда ... если только вы не сохраните фамилию этого парня длиной до 666 символов. В этом случае, возможно, varchar (1028) имеет больше смысла.

И в случае, если это полезно, вот как может выглядеть varchar 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 символов (латиница 1)

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

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

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

Надеюсь это поможет :)


Вы используете MySQL, и вопрос о MSSQL
Богдан Март

6

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


3

Я не проверял это в последнее время, но в прошлом я знал, что в случае с драйвером 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.