Каждый раз, когда вы настраиваете новую таблицу SQL или добавляете новый столбец varchar
в существующую таблицу, мне интересно, что самое лучшее для length
.
Итак, скажем, у вас есть столбец с именем name
типа varchar
. Итак, вы должны выбрать длину. Я не могу придумать имя > 20 символов, но вы никогда не узнаете. Но вместо того, чтобы использовать 20, я всегда округляю до следующего числа 2 ^ n. В этом случае я бы выбрал 32 как длину. Я делаю это, потому что с точки зрения компьютерного ученого число 2 ^ n выглядит больше even
для меня, чем другие числа, и я просто предполагаю, что архитектура под ними может обрабатывать эти числа немного лучше других.
С другой стороны, сервер MSSQL, например, устанавливает значение длины по умолчанию равным 50, когда вы решите создать столбец varchar. Это заставляет меня думать об этом. Почему 50? это просто случайное число или на основе средней длины столбца или что?
Он также может быть - или, возможно, - что разные реализации SQL-серверов (например, MySQL, MSSQL, Postgres,...) имеют разные наилучшие значения длины столбца.
Никаких СУБД, которые я знаю, не имеет никакой "оптимизации", которая сделает длину 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
имеет огромное значение для производительности.
VARCHAR(255)
и VARCHAR(2)
занимают ровно столько же места на диске! Поэтому единственная причина ограничить это, если у вас есть конкретная потребность в ее уменьшении. В противном случае сделайте все 255.
В частности, при сортировке более крупный столбец занимает больше места, поэтому, если это ущемляет производительность, вам нужно беспокоиться об этом и сделать их меньше. Но если вы только когда-либо выбираете 1 строку из этой таблицы, вы можете просто сделать их всего 255, и это не имеет значения.
VARCHAR(MAX)
? Пространство не единственное соображение при моделировании базы данных. Домен, который вы моделируете, должен управлять типами данных и размерами.
VARCHAR(MAX)
отличается от varchar(255)
или varchar(65535)
- varchar max является типом text
типа данных. И к вашему мнению - если бы он знал, что такое «область, которую он моделировал», он бы не задавал этот вопрос. Ясно, что он не знает, насколько большими будут его данные, и я заверяю его, что создание полного размера ничего не вредит.
Наилучшее значение - это значение, которое подходит для данных, определенных в базовом домене.
Для некоторых доменов VARCHAR(10)
подходит для атрибута Name
, для других доменов VARCHAR(255)
может быть лучшим выбором.
Всякий раз, когда я настраиваю новую таблицу 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
Добавляя к ответу 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 нулевой байт
Надеюсь, что это поможет:)
Всегда проверяйте у своего эксперта в области бизнеса. Если это вы, посмотрите на отраслевой стандарт. Если, например, рассматриваемый домен является фамилией естественного человека (фамилия), то для британского бизнеса я бы пошел в каталог UK Govtalk для стандартов данных информацию о человеке и узнайте, что фамилия будет от 1 до 35 символов.
Я не проверял это в последнее время, но в прошлом я знал, что драйвер JDBC зарезервирует кусок памяти во время выполнения запроса, чтобы вернуть возвращаемый набор результатов. Размер блока памяти зависит от определений столбцов и размера выборки. Таким образом, длина столбцов varchar2 влияет на объем памяти. Это вызвало серьезные проблемы с производительностью для меня много лет назад, так как мы всегда использовали varchar2 (4000) (максимальный в то время), а сбор мусора был намного менее эффективным, чем сегодня.