TEXT и VARCHAR
Тема дорожной карты · PostgreSQL
В PostgreSQL TEXT и VARCHAR (character varying) функционально почти идентичны: оба типа хранятся с использованием одного и того же внутреннего механизма varlena без какого-либо различия в производительности хранения или извлечения — это важное отличие от других баз данных, например Oracle. VARCHAR(n) принудительно ограничивает длину значения n символами и вызывает ошибку при попытке вставки превышающего значения, тогда как TEXT не имеет ограничения длины; CHAR(n) дополняет значения пробелами до ровно n символов и, как правило, не рекомендуется при администрировании баз данных PostgreSQL из-за расточительного потребления пространства. При настройке производительности PostgreSQL ни один тип не является предпочтительным с точки зрения хранения, поскольку оба используют TOAST (The Oversized-Attribute Storage Technique) для прозрачного сжатия и выноса за пределы страницы значений длиннее примерно 2 КБ. Многие опытные администраторы PostgreSQL предпочитают TEXT за его простоту и используют ограничения CHECK при необходимости валидации длины, делая логику ограничения явной и независимо изменяемой. Понимание эквивалентности TEXT и VARCHAR в PostgreSQL помогает разработчикам, мигрирующим с других баз данных, и позволяет принимать взвешенные решения при проектировании схем.
Как это работает
TEXT и VARCHAR покрывает numeric (int, bigint, numeric, real, double), character (text, varchar, char — берите text, кроме реального лимита), date/time (timestamp, timestamptz — всегда tz-вариант), boolean, JSONB (запросимый JSON с GIN-индексами), массивы (int[], text[]), ranges (int4range, tsrange), UUID, network (inet, cidr), геометрические, кастомные через DOMAIN или CREATE TYPE. Postgres необычно богат — используйте типы, а не перегружайте text/JSONB.
Когда применять
Всегда timestamptz (timestamp with time zone) для меток времени — Postgres хранит UTC + конвертирует на показ. numeric(10,2) для денег, никогда real/float (округление). uuid для ID, видимых клиентам (нет утечки объёма vs integer); bigint — для внутренних high-volume последовательностей. JSONB (не JSON) — бинарный, индексируется, быстрее. Enum использовать аккуратно (тяжело мигрировать); lookup-таблица часто яснее.
Типичные ошибки
Ловушки TEXT и VARCHAR: timestamp (без tz) и тихое хранение локального (DST-ужас); varchar(255) "потому что MySQL" (в Postgres нет perf-выгоды — используйте text); JSON вместо JSONB (текст, медленней, без индексов); float для денег (копейка тут, копейка там — за годы). Прочтите справочник типов — окупается лучшими решениями по схеме.