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

197

Каждый раз, когда вы настраиваете новую таблицу SQL или добавляете новый столбец varchar в существующую таблицу, мне интересно, что самое лучшее для length.

Итак, скажем, у вас есть столбец с именем name типа varchar. Итак, вы должны выбрать длину. Я не могу придумать имя > 20 символов, но вы никогда не узнаете. Но вместо того, чтобы использовать 20, я всегда округляю до следующего числа 2 ^ n. В этом случае я бы выбрал 32 как длину. Я делаю это, потому что с точки зрения компьютерного ученого число 2 ^ n выглядит больше even для меня, чем другие числа, и я просто предполагаю, что архитектура под ними может обрабатывать эти числа немного лучше других.

С другой стороны, сервер MSSQL, например, устанавливает значение длины по умолчанию равным 50, когда вы решите создать столбец varchar. Это заставляет меня думать об этом. Почему 50? это просто случайное число или на основе средней длины столбца или что?

Он также может быть - или, возможно, - что разные реализации SQL-серверов (например, MySQL, MSSQL, Postgres,...) имеют разные наилучшие значения длины столбца.

Теги:
sql-server

7 ответов

162
Лучший ответ

Никаких СУБД, которые я знаю, не имеет никакой "оптимизации", которая сделает длину 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. См. этот ответ от Aaron Bertrand, который показывает, что заявленная длина столбцов nvarchar или VARCHAR имеет огромное значение для производительности.

  • 28
    На самом деле, есть разница между VARCHAR (255) и VARCHAR (500), даже если вы поместите 1 символ в такой столбец. Значение, добавленное в конец строки, будет целым числом, в котором хранится фактическая длина хранимых данных. В случае VARCHAR (255) это будет 1-байтовое целое число. В случае VARCHAR (500) это будет 2 байта. это небольшая разница, но нужно знать об этом. У меня нет никаких данных о том, как это может повлиять на производительность, но я предполагаю, что она настолько мала, что ее не стоит исследовать.
  • 0
    @NB: это то, что я имел в виду для «магического» значения SQL Server 255. Спасибо за разъяснения.
Показать ещё 6 комментариев
48

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

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

Смотрите: Каковы оптимальные размеры varchar для MySQL?

  • 6
    Почему бы не сделать их всех VARCHAR(MAX) ? Пространство не единственное соображение при моделировании базы данных. Домен, который вы моделируете, должен управлять типами данных и размерами.
  • 5
    @Oded VARCHAR(MAX) отличается от varchar(255) или varchar(65535) - varchar max является типом text типа данных. И к вашему мнению - если бы он знал, что такое «область, которую он моделировал», он бы не задавал этот вопрос. Ясно, что он не знает, насколько большими будут его данные, и я заверяю его, что создание полного размера ничего не вредит.
Показать ещё 5 комментариев
30

Наилучшее значение - это значение, которое подходит для данных, определенных в базовом домене.

Для некоторых доменов VARCHAR(10) подходит для атрибута Name, для других доменов VARCHAR(255) может быть лучшим выбором.

16

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

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

Еще одна вещь, которую следует учитывать у Билла Карвина:

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

В принципе, просто придумайте разумные бизнес-ограничения и ошибку при немного большем размере. Как уже отмечалось, фамилии в Великобритании обычно составляют от 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(1028)   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
  • 3
    Визуализация для победы! Я часто обращаюсь к этому блоку, когда проектирую. Так полезно.
12

Добавляя к ответу 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 нулевой байт

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

  • 0
    Вы используете MySQL, и вопрос о MSSQL
  • 1
    Он отметил (taged) 3 sql строит ...
5

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

3

Я не проверял это в последнее время, но в прошлом я знал, что драйвер JDBC зарезервирует кусок памяти во время выполнения запроса, чтобы вернуть возвращаемый набор результатов. Размер блока памяти зависит от определений столбцов и размера выборки. Таким образом, длина столбцов varchar2 влияет на объем памяти. Это вызвало серьезные проблемы с производительностью для меня много лет назад, так как мы всегда использовали varchar2 (4000) (максимальный в то время), а сбор мусора был намного менее эффективным, чем сегодня.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню