В PostgreSQL
varchar(255) ведёт себя так же, как столбец типа
text; единственное отличие — у
varchar есть ограничение на длину. Тип
varchar(n) всегда работал именно так. Если вы видите в PostgreSQL столбец
varchar(255), то зачастую это потому, что разработчик сначала работал с другой СУБД и перенёс свои прежние представления о том, как должен работать
varchar(n).
Когда использовать
text, а когда
varchar?
Если есть бизнес-требование ограничить максимальную длину значения или столбец индексируется с помощью B-tree, стоит рассмотреть
varchar(n). Если такого требования нет — используйте
text и не думайте, что делаете что-то неправильно.
Более того, в документации PostgreSQL говорится:
Хотя в некоторых других СУБД тип character(n) может иметь преимущества по производительности, в PostgreSQL таких преимуществ нет. Более того, character(n)
обычно является самым медленным из трёх вариантов из-за дополнительных затрат на хранение. В большинстве случаев вместо него следует использовать text или character varying
Почему изменить
varchar(n) на
text ничего не стоит?
Потому что это всего лишь изменение метаданных. Физическое хранение данных у этих типов одинаковое.
Метаданные хранятся в таблице
pg_attribute, поэтому изменение типа сводится к обновлению записи в этой таблице. Сами данные остаются без изменений, поэтому не требуется ни переписывать таблицу, ни менять формат хранения.
А вот с
char всё иначе
При миграции с
char на
text для каждого значения выполняется
rtrim, поскольку неявное приведение
char к
text автоматически удаляет завершающие пробелы.
Это уже значительно более затратная операция, чем простое изменение метаданных, поэтому PostgreSQL приходится переписывать таблицу.
Как PostgreSQL хранит строки. PostgreSQL использует формат хранения переменной длины для всех строковых типов данных.
Данные могут храниться либо непосредственно в строке таблицы (inline), либо с использованием механизма
TOAST (
The Oversized-Attribute Storage Technique), который отвечает за сжатие и вынесение больших значений за пределы основной таблицы. Обычно TOAST начинает использоваться, когда размер строки превышает примерно 2 КБ.
И
varchar(n), и
text используют один и тот же механизм хранения, включая TOAST.
Когда действительно стоит использовать
varchar(n)?
Используйте
varchar(n), когда ограничение длины — это бизнес-правило, которое должна контролировать сама база данных. Например:
country_code varchar(2), -- ISO 3166-1
currency_code varchar(3), -- ISO 4217
us_zip_code varchar(5), -- 5 цифр
sku varchar(20), -- ограничения внешних систем
Стоит ли использовать
varchar для
country_code и
currency_code? Конечно. Международные стандарты жёстко определяют длину этих кодов.
Для
SKU ограничение длины также может диктоваться внешними требованиями.
Что касается
us_zip_code, то на практике нередко возникает необходимость поддерживать расширенный формат ZIP+4. Со временем такие столбцы вообще могут быть переименованы в
postal_code, чтобы поддерживать международные почтовые индексы.
В таких случаях
varchar одновременно обеспечивает и необходимое ограничение, и достаточную гибкость.
Проще говоря,
varchar помогает обеспечить соблюдение бизнес-правил.
Индексируемые столбцы? Рассмотрите
varchar(n)Само по себе индексирование столбцов типа
text не является проблемой, однако есть нюанс.
varchar(n) может служить дополнительной защитой для индексируемых столбцов (например, если
username используется не просто как отображаемое имя, а для поиска, аутентификации или загрузки профиля).
Почему?
Потому что PostgreSQL не сможет создать запись в B-tree-индексе, если её размер превышает примерно
2704 байта.
На самом деле ограничение распространяется не на исходный размер строки, а на её
сжатый размер, поэтому назвать точный предел в символах невозможно: разные строки сжимаются по-разному.
Ограничение длины через
varchar(n) позволяет предотвратить ситуацию, когда приложение пытается сохранить значение, которое невозможно проиндексировать.
👉
Java Portal