В чем разница типов text и varchar в PostgreSQL
Что проверяют
Знаете ли вы, как PostgreSQL хранит строки на самом деле, или переносите привычки из MySQL и Oracle. Следом часто спрашивают, как тогда ограничить длину поля и что увидит Go-код, если лимит превышен.
Как отвечать
Главное: в PostgreSQL text, varchar без длины и varchar(n) хранятся одинаково, как строка переменной длины с коротким заголовком. Разницы в скорости и в размере на диске нет. varchar(n) добавляет ровно одно: проверку длины при записи.
varchar(n):nсчитается в символах, а не в байтах. Превышение даёт ошибкуvalue too long for type character varying(n)с кодом22001. Исключение: явное приведение::varchar(n)молча обрежет строку;text: без ограничения, кроме общего предела поля в 1 ГБ. Длинные значения уходят в TOAST и сжимаются, как и уvarchar;char(n): дополняет значение пробелами до длины и работает не быстрее, а местами медленнее. В новых схемах его не используют.
Практический вывод совпадает с рекомендацией вики PostgreSQL: берите text, а если бизнес-правило требует лимита, пишите CHECK (char_length(code) <= 10). Такое ограничение проще менять. Увеличение n у varchar таблицу не переписывает, а вот уменьшение заставит проверить все строки под блокировкой.
Со стороны Go оба типа читаются в string. Для колонок с NULL нужен *string, sql.NullString или pgtype.Text из pgx, иначе Scan упадёт на первом же пустом значении. Ошибку превышения длины удобно разбирать через errors.As в *pgconn.PgError с проверкой Code == "22001", чтобы вернуть клиенту понятный ответ 400, а не 500. Валидацию длины при этом держат и в самом сервисе, база здесь последний рубеж.
Где спотыкаются
Утверждают, что varchar быстрее или компактнее text. В PostgreSQL это неверно, и интервьюер обычно ждёт именно этой поправки.
Пишут varchar(255) по привычке из MySQL, где длина влияла на формат хранения. Здесь это просто случайный лимит, который однажды отрежет чей-то длинный адрес.
Путают символы и байты. Кириллица в UTF-8 занимает по два байта на символ, но в varchar(10) всё равно поместятся те же 10 символов.