В чем разница между типами данных JSON и JSONB в PostgreSQL

Ответ

Основное различие между JSON и JSONB в PostgreSQL заключается в способе хранения данных, что напрямую влияет на производительность и возможности.

  • JSON: Хранит точную текстовую копию входных данных. Сохраняются все пробелы, порядок ключей и дубликаты ключей. При каждом запросе данные требуют повторного парсинга.

  • JSONB (B означает Binary): Хранит данные в декомпозированном бинарном формате. Пробелы удаляются, порядок ключей не сохраняется (они сортируются), а при наличии дубликатов сохраняется только последнее значение. Данные парсятся один раз при вставке.

Ключевые отличия

Характеристика JSON JSONB
Хранение Текст Бинарный формат
Скорость вставки Быстрее (нет преобразования) Медленнее (требуется парсинг)
Скорость чтения Медленнее (требуется парсинг) Значительно быстрее
Индексация Не поддерживается Поддерживаются GIN-индексы
Пробелы и порядок Сохраняются Не сохраняются

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

-- Создаем таблицу для демонстрации
CREATE TABLE products (
  id serial PRIMARY KEY,
  attributes_json JSON,
  attributes_jsonb JSONB
);

-- Вставляем данные с пробелами и разным порядком ключей
INSERT INTO products (attributes_json, attributes_jsonb)
VALUES
  ('{"price": 99.9, "name": "Gadget"  }', '{"price": 99.9, "name": "Gadget"  }');

-- Проверяем, как данные сохранились
SELECT attributes_json, attributes_jsonb FROM products;
-- attributes_json: {"price": 99.9, "name": "Gadget"  } (как есть)
-- attributes_jsonb: {"name": "Gadget", "price": 99.9} (отформатировано)

-- Создаем индекс для JSONB для ускорения запросов
CREATE INDEX idx_products_attributes ON products USING GIN (attributes_jsonb);

-- Этот запрос будет работать очень эффективно благодаря индексу
SELECT * FROM products WHERE attributes_jsonb @> '{"name": "Gadget"}';

Рекомендация: Почти всегда следует использовать JSONB, так как он обеспечивает значительно лучшую производительность запросов и поддерживает индексацию. JSON стоит выбирать только в редких случаях, когда необходимо сохранить исходное форматирование JSON-документа.

Ответ 18+ 🔞

Давай разберёмся с этой парой, блядь, JSON и JSONB. Ситуация, внатуре, как с двумя братанами-близнецами, но один — просто текст, а второй — прокачанный бинарный монстр. Ёпта, сейчас всё разжуем.

JSON — это как архив с бумажками. Засунули туда бумажку с надписью {"price": 99.9, "name": "Gadget" }, он её так и хранит, со всеми пробелами, порядком и даже если ты туда же, сука, второй раз ключ "name" запишешь. Каждый раз, когда надо прочитать, этот архив распаковывают и парсят заново. Медленно, пиздец как неудобно.

JSONB (это B от binary, ёпта) — это уже не архив, а нормальная база данных внутри базы данных. Ты ему суёшь ту же бумажку, а он её, блядь, моментально разбирает на запчасти: выкидывает лишние пробелы, ключи сортирует, дубликаты выпиливает (оставляет последний, хитрая жопа). И всё это складывает в оптимизированный бинарный формат. Парсинг — один раз при вставке, а потом читается мгновенно.

Так в чём разница, блядь? Смотри таблицу, чтобы не еб@ть мозг:

Прикол JSON JSONB
Как лежит Текст, как есть Разобранный бинарник
Запись Быстро (просто скопировал текст) Помедленнее (надо разобрать и упаковать)
Чтение Медленно (каждый раз парсить) Овердохуища быстрее (уже готово)
Индексы Нельзя, нихуя Можно! GIN-индексы, красота!
Порядок и мусор Сохраняет всё Выкидывает нахуй

Пример из жизни, чтобы вообще всё стало ясно:

-- Делаем табличку для экспериментов
CREATE TABLE products (
  id serial PRIMARY KEY,
  attributes_json JSON,
  attributes_jsonb JSONB
);

-- Пихаем данные. Смотри, в JSONB пробелы лишние схавает.
INSERT INTO products (attributes_json, attributes_jsonb)
VALUES
  ('{"price": 99.9, "name": "Gadget"  }', '{"price": 99.9, "name": "Gadget"  }');

-- Смотрим, что получилось
SELECT attributes_json, attributes_jsonb FROM products;
-- attributes_json: {"price": 99.9, "name": "Gadget"  } (всё на месте, даже пробелы в конце)
-- attributes_jsonb: {"name": "Gadget", "price": 99.9} (причёсано, ключи переставлены)

-- Вот магия! На JSONB можно навесить индекс, и поиск станет мгновенным.
CREATE INDEX idx_products_attributes ON products USING GIN (attributes_jsonb);

-- Этот запрос, блядь, выстрелит как из пушки благодаря индексу.
SELECT * FROM products WHERE attributes_jsonb @> '{"name": "Gadget"}';

Итог, ёпта: Если тебе не нужно срочно сохранить, блядь, точную копию JSON-документа со всеми его тараканами (а такое бывает раз в пятилетку), то всегда, сука, выбирай JSONB. Он быстрее, умнее и с индексами дружит. JSON — это для музея, а JSONB — для боя. Всё, вопрос закрыт.