В чем разница между типами данных VARCHAR и TEXT в SQL?

«В чем разница между типами данных VARCHAR и TEXT в SQL?» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

VARCHAR и TEXT — это типы данных для хранения символьных строк, но с фундаментальными различиями в использовании и внутреннем устройстве (на примере MySQL/MariaDB).

Основные различия:

Критерий VARCHAR(n) TEXT
Максимальная длина Ограничена значением n (до 65,535 байт, зависит от кодировки и версии СУБД). Большие объемы. TEXT ~64KB, MEDIUMTEXT ~16MB, LONGTEXT ~4GB.
Определение длины Обязательно указывается при создании: VARCHAR(255). Указывается только тип: TEXT.
Хранение In-row storage: Значение хранится в той же строке таблицы, если помещается в лимит страницы. Более быстрое чтение. Off-row storage: В строке таблицы хранится лишь указатель (pointer), а сами данные — отдельно. Чтение может требовать дополнительного обращения.
Индексация Можно создать индекс по всему полю. В MySQL нельзя проиндексировать поле TEXT целиком, можно только указать длину префикса (Prefix Index): CREATE INDEX idx ON table (text_column(100)).
Выделение памяти Выделяется память под максимально возможную длину (n), что может быть неэффективно для длинных значений. Выделяется память под фактическую длину строки + накладные расходы на указатель.
Использование в ключах Может быть частью PRIMARY KEY или UNIQUE ключа. Не может быть частью ключа (кроме полнотекстовых индексов).

Практический пример и рекомендации:

CREATE TABLE articles (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,        -- Заголовок, всегда ограниченной длины
    slug VARCHAR(200) UNIQUE NOT NULL,  -- URL-адрес, нужен UNIQUE индекс
    excerpt VARCHAR(500),               -- Короткое описание
    content TEXT NOT NULL,              -- Основной текст статьи, может быть очень длинным
    meta_description TEXT               -- Для SEO, тоже может быть длинным
);

Когда что использовать:

  • Используйте VARCHAR: Для полей с предсказуемой и относительно небольшой длиной: имена (VARCHAR(100)), email (VARCHAR(255)), коды, хэши, заголовки. Когда необходимо наложить ограничение по длине или создать индекс по всему полю.
  • Используйте TEXT: Для неограниченного или потенциально очень большого текста: тело статьи, комментарии пользователей, лог-сообщения, JSON/XML-данные. Когда индексация по префиксу достаточна или не требуется.

Важно: Конкретные лимиты и поведение (особенно по хранению) могут отличаться в PostgreSQL, SQL Server и других СУБД.