Должен ли я добавить произвольный предел длины для столбцов VARCHAR?

35

Согласно документации в PostgreSQL , нет никакой разницы в производительности между VARCHAR, VARCHAR(n)и TEXT.

Должен ли я добавить произвольный предел длины в столбце имени или адреса ?

Редактировать: не обман

Я знаю, что этот CHARтип - пережиток прошлого, и мне интересны не только производительность, но и другие плюсы и минусы, такие как Эрвин, в своем удивительном ответе.

Даниэль Серодио
источник

Ответы:

45

Ответ - нет .
Не добавляйте модификатор длины, varcharесли вы можете избежать этого. В большинстве случаев вам вообще не нужно ограничение длины. Просто используйте textдля всех символьных данных. Сделайте это varchar(без модификатора длины), если вам нужно оставаться совместимым с СУБД, которых нет text.

Производительность почти то же самое - textэто немного быстрее , в редких случаях , и вы сохраните циклы для проверки на длину.

Если вам действительно нужно установить максимальную длину, все равно используйте textи добавьте проверочное ограничение для этого:

ALTER TABLE tbl ADD CONSTRAINT tbl_col_len CHECK (length(col) < 51);

Вы можете изменить или удалить такое ограничение в любое время без необходимости связываться с определением таблицы и всеми зависимыми объектами (представлениями, функциями, внешними ключами, ...)

С модификаторами длины вы можете столкнуться с такими проблемами, как эта или эта или эта ...

В PostgreSQL 9.1 появилась новая функция, которая несколько облегчает боль. Я цитирую примечания к выпуску здесь :

Позволяют ALTER TABLE ... SET DATA TYPEизбежать переписывания таблиц в соответствующих случаях (Ноа Миш, Роберт Хаас)

Например, преобразование varcharстолбца в текст больше не требует переписывания таблицы. Однако увеличение ограничения длины для varcharстолбца все еще требует перезаписи таблицы.

Эрвин Брандштеттер
источник
Я думаю, что этот ответ был бы намного лучше, если бы он был просто «не добавляйте произвольные ограничения к реальной базе данных никогда». Я чувствую, что многие из этого ответа нуждаются в исправлениях и дополнительной информации, но это совершенно не по теме и будет отвлекать от вашего заключения, с которым я полностью согласен.
Эван Кэрролл
Да, все основано на версиях Postgres до 9.1 - 6 лет назад. Немного запылено, но основной совет все еще хорош.
Эрвин Брандштеттер
Является ли хорошей или плохой идеей добавить проверочное ограничение для каждого текстового столбца с целью проверки работоспособности и обеспечения того, чтобы ошибка в клиенте не занимала все дисковое пространство базы данных при вставке очень большого текста?
Код
@ Код: это жизнеспособный вариант. Если у вас много столбцов с одинаковым ограничением, рассмотрите домены . Или, в varchar(n)конце концов, для простоты - если недостатки не влияют на вас. (Предел не является произвольным в вашем случае, если вы хотите применить фактическую максимальную длину.)
Эрвин Брандштеттер
12

Если вы видите ограничение длины как своего рода проверочное ограничение, чтобы убедиться, что вы проверяете данные, тогда добавьте да. На самом деле вы можете захотеть не использовать определение длины, а реальное ограничение проверки, чтобы ускорить изменение предела.

Чтобы изменить (увеличить) ограничение длины, вам нужно запустить процедуру, выполнение ALTER TABLEкоторой может занять много времени (из-за возможной перезаписи таблицы), в течение которой необходима исключительная блокировка таблицы.

Изменение (то есть удаление и повторное создание) проверочного ограничения - это очень короткая операция, требующая только чтения данных таблицы, она не изменит никаких строк. Так что это будет намного быстрее (что, в свою очередь, означает, что эксклюзивная блокировка таблицы будет удерживаться в течение гораздо более короткого промежутка времени).

Во время работы нет никакой разницы между a text, a varcharили varchar(5000)столбцом.

a_horse_with_no_name
источник
из простого любопытства, почему вы думаете, что эта проверка длины не может быть выполнена на клиентском приложении во время сбора данных?
PirateApp
4
@PirateApp: потому что очень часто будет более одного приложения или какого-либо внешнего источника данных (подумайте, ночной пакетный импорт). И почти всегда база данных (и данные) живут дольше, чем одно приложение.
a_horse_with_no_name
2

Вопрос конкретно в том, можно ли добавить произвольный предел длины в столбцы VARCHAR?

На это ответ просто «нет». Нет ничего, что могло бы оправдать добавление произвольного ограничения, как это было бы в низших базах данных, которые поддерживают varchar(max)или используют соглашения, подобные varchar(255). Однако, если спецификация касается предела, я думаю, что ответ становится намного более сложным, особенно в современных версиях PostgreSQL. И для этого я бы склонялся к ДА .

На мой взгляд, ограничение является разумным выбором, если этого требует спецификация. Особенно для более разумных нагрузок. Если ни по какой другой причине, то для сохранения метаданных.

Из моего ответа здесь, индекс производительности для CHAR против VARCHAR (Postgres) , где я обращаюсь к значению метаданных.

Если бы я нашел спецификацию с текстовыми клавишами переменной длины, которые были бы значимыми и которые я доверял, чтобы иметь постоянную максимальную длину, я бы varcharтоже использовал . Тем не менее, я не могу думать ни о чем, что соответствует этим критериям.

Эван Кэрролл
источник
1

Похоже, что может быть некоторая разница в производительности, если VARCHARрегулярно использовать для хранения очень больших строк, поскольку «длинные строки сжимаются системой автоматически» и «очень длинные значения также хранятся в фоновых таблицах». Теоретически это будет означать, что большой объем запросов для очень длинного строкового поля будет медленнее, чем для короткого строкового поля. Вы, вероятно, никогда не столкнетесь с этой проблемой, так как имена и адреса не будут очень длинными.

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

Эдвард
источник
1
AFAIK нет разницы в TOASTing varchar и текстовых полей.
Дезсо
VARCHARявляется чисто синтаксическим сахаром, поскольку TEXTв Postgres нет никакой разницы в хранении; Упомянутое вами сжатие и хранение в фоновой таблице выполняется на основе фактической длины данных в столбце, а не на метаданных столбца. Столбцы TEXT хранятся внутри как varlenaструктура C (которая представляет собой массив переменной длины с первыми 4 байтами, хранящими длину при создании / обновлении), и именно эта структура оптимизируется на основе ее длины.
Cowbert