JSON и JSONB

Тема дорожной карты · PostgreSQL

PostgreSQL предлагает два типа данных для хранения JSON-документов: JSON и JSONB; понимание их различий необходимо любому разработчику реляционных баз данных, работающему с полуструктурированными данными. JSON хранит исходный текст JSON-ввода дословно, сохраняя пробелы и порядок дублирующихся ключей, что делает его подходящим для архивных или точно-воспроизводимых сценариев. JSONB (JSON Binary) при записи разбирает JSON во внутренний двоичный формат: вставка выполняется немного медленнее, но запросы значительно быстрее, поскольку поддерживается GIN-индексирование и доступ через операторы без повторного разбора текста при каждом чтении. В PostgreSQL JSONB почти всегда является предпочтительным выбором для данных приложения, поскольку поддерживает оператор вхождения @>, проверку наличия ключа ? и операторы пути -> / ->> для оптимизации запросов, а также прямое создание CREATE INDEX USING GIN для ускорения поиска по миллионам документов в реляционной базе данных.

Как это работает

JSON и JSONB покрывает 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-таблица часто яснее.

Типичные ошибки

Ловушки JSON и JSONB: timestamp (без tz) и тихое хранение локального (DST-ужас); varchar(255) "потому что MySQL" (в Postgres нет perf-выгоды — используйте text); JSON вместо JSONB (текст, медленней, без индексов); float для денег (копейка тут, копейка там — за годы). Прочтите справочник типов — окупается лучшими решениями по схеме.

Связанные понятия

Полезные ресурсы