CHAR vs VARCHAR: разница и когда что

Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.

Зачем знать разницу

На собеседовании для junior-аналитика это популярный вопрос: «чем отличается CHAR от VARCHAR?». Казалось бы, оба — строки. Но ответ показывает, читали ли вы документацию или только копипастили с Stack Overflow.

Для аналитика практически это проявляется так: на собесе спросят, почему сравнение WHERE code = 'AB' не работает (потому что в базе CHAR(5) и лежит 'AB ' с паддингом). В продакшене встречаете таблицы, где поле country_code — CHAR(2). В ETL приходят файлы с фиксированной длиной поля — тут CHAR семантически правильнее.

Плюс есть performance-нюансы: CHAR всегда занимает фиксированное место (быстрее на чтение, больше по памяти), VARCHAR — только используемое (экономнее, но overhead на длину).

В статье:

  • Короткий ответ и сравнительная таблица
  • CHAR — фиксированная длина с паддингом
  • VARCHAR — переменная длина
  • Разница в Postgres / MySQL / MSSQL
  • Performance
  • Когда что выбирать
  • TEXT, BLOB, CLOB — другие типы строк

Короткий ответ

  • CHAR(n) — фиксированная длина. Всегда n символов. Короткие строки дополняются пробелами справа.
  • VARCHAR(n) — переменная длина, максимум n. Только используемое.
  • TEXT — без ограничения длины (Postgres / MySQL).

Сравнение

CHAR(n) VARCHAR(n) TEXT
Длина фиксированная n до n без лимита
Padding пробелы справа нет нет
Память n × 4 байта (UTF-8) длина + 1-4 длина + 4
Скорость чтения быстрее (фикс.) чуть медленнее аналогично VARCHAR
Когда выбирать коды, хеши фикс. длины обычный текст длинный текст

Пример padding

CREATE TABLE t (c CHAR(5));
INSERT INTO t VALUES ('AB');

SELECT c, LENGTH(c), c = 'AB' FROM t;

Результат:

  • c = 'AB ' (с пробелами!)
  • LENGTH(c) = 5
  • c = 'AB' — в разных СУБД по-разному

Postgres

c = 'AB' возвращает TRUE (Postgres игнорирует trailing spaces при сравнении).

MySQL

Тоже сравнивает без учёта паддинга по умолчанию (зависит от collation).

MSSQL

С ANSI_PADDING OFF — TRUE. С ON — FALSE. По умолчанию зависит от настроек.

Правило: если собираетесь сравнивать CHAR-поле как строку — всегда TRIM() для надёжности.

Примеры использования

CHAR — хорошо

-- коды фиксированной длины
country_code CHAR(2)   -- 'RU', 'US', 'KZ'
currency_code CHAR(3)  -- 'USD', 'EUR', 'RUB'

-- хеши
md5_hash CHAR(32)

-- фиксированные ID
some_id CHAR(12)

VARCHAR — стандарт

-- имена, email
name VARCHAR(100)
email VARCHAR(255)

-- описания / комментарии
description VARCHAR(500)

TEXT — длинный текст

-- статьи, отзывы
article_body TEXT
review TEXT

Производительность

CHAR

Плюсы:

  • Фиксированное смещение в row → быстрое чтение
  • Нет overhead на длину

Минусы:

  • Больше памяти при коротких значениях (паддинг пустотой)
  • Trim при выборке может быть нужен

VARCHAR

Плюсы:

  • Только используемое место
  • Нет паддинга

Минусы:

  • Overhead 1-4 байта на длину
  • Вариативный размер row → сложнее layout

TEXT в Postgres

TEXT = VARCHAR без ограничения. Внутри то же самое. Нет performance разницы.

В других СУБД может отличаться (MySQL хранит TEXT off-row).

В Postgres

Специфика Postgres:

  • VARCHAR(n)TEXT с check constraint на длину
  • Нет разницы в производительности между VARCHAR и TEXT
  • CHAR считается анахронизмом (padding мешает)

Рекомендация Postgres community: используйте TEXT (или VARCHAR без длины) везде, где нет строгого требования на фиксированную длину.

В MySQL

  • CHAR(n) до 255
  • VARCHAR(n) до 65 535
  • TEXT может храниться off-row (performance impact)
  • TINYTEXT, MEDIUMTEXT, LONGTEXT — разные limits

MySQL часто имеет реальную разницу CHAR vs VARCHAR по perf на некоторых workloads.

В MSSQL

  • CHAR / VARCHAR — ASCII
  • NCHAR / NVARCHAR — Unicode (UTF-16)
  • Всегда используйте N-варианты для текста

Когда выбирать CHAR

  • Строгая фиксированная длина (коды, хеши)
  • Быстрое чтение критично
  • Консистентность (уровень DB, не приложения)

Когда выбирать VARCHAR / TEXT

  • Переменная длина (90% случаев)
  • Экономия памяти на коротких значениях
  • Более стандартный подход

На собесе

«Разница CHAR и VARCHAR?» CHAR фиксированная длина с паддингом. VARCHAR — переменная до n.

«Что быстрее?» CHAR теоретически быстрее из-за фикс. offset, но практически разница микроскопичная.

«Когда CHAR?» Когда поле всегда одной длины (country code, hash).

«Postgres: TEXT или VARCHAR?» Одинаково. TEXT проще — без limit.

Частые ошибки

1. CHAR для телефона

Телефоны разной длины (10 цифр vs 11 с + ). VARCHAR.

2. VARCHAR(255) "на всякий случай"

Классика. В большинстве СУБД 255 — не magic number. Подбирайте адекватно.

3. Сравнение CHAR без TRIM

Может работать, может — нет. Зависит от collation / config.

4. TEXT для всего

В MySQL TEXT хранится off-row → slower queries. Используйте VARCHAR если знаете max.

Связанные темы

FAQ

Postgres рекомендует VARCHAR или TEXT?

TEXT. VARCHAR без length то же самое.

CHAR(n) реально быстрее?

Теоретически да, на тысячах операций — возможно. В аналитике неощутимо.

NCHAR vs CHAR?

NCHAR — Unicode (UTF-16). Для международного текста.

Максимум VARCHAR?

Postgres: 1 GB. MySQL: 65 535 байт на row (с учётом всех VARCHAR). MSSQL: 8000 для VARCHAR / VARCHAR(MAX) до 2 GB.


Тренируйте SQL — откройте тренажёр с 1500+ вопросами для собесов.