Лучшие практики для длины столбца SQL varchar - PullRequest
256 голосов
/ 28 ноября 2011

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

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

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

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

Ответы [ 8 ]

213 голосов
/ 28 ноября 2011

Нет СУБД, о которой я знаю, имеет какую-либо "оптимизацию", которая позволит 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 миллиона строк сверху) указывает на то, что no rewrite занимает место.

Редактировать 2017-01-24

Кажется, я (хотя бы частично) ошибался насчет SQL Server. Посмотрите этот ответ от Аарона Бертрана , который показывает, что заявленная длина столбцов nvarchar или varchar имеет огромное значение для производительности.

57 голосов
/ 28 ноября 2011

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

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

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

38 голосов
/ 19 мая 2016

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

Тем не менее, вы все равно должны предвидеть потенциальные последствия для хранилища и производительности при установке высокого предела 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
30 голосов
/ 28 ноября 2011

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

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

14 голосов
/ 28 ноября 2011

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

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

6 голосов
/ 28 ноября 2011

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

3 голосов
/ 27 июня 2017

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

0 голосов
/ 05 июля 2019

В некотором смысле вы правы, хотя все, что меньше 2 ^ 8 символов, все равно будет регистрироваться как байт данных.

Если вы учитываете базовый символ, который оставляет что-либо с VARCHAR <255, занимающим такое же количество места. </p>

255 является хорошим базовым определением, если только вы особо не хотите сократить чрезмерный ввод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...