В чем преимущества JSONB над JSON в базе данных?
Что проверяют
Понимаете ли вы, что в PostgreSQL это два разных типа, а не синонимы, и умеете ли выбрать нужный.
Как отвечать
json хранит документ как текст ровно в том виде, в каком он пришёл. jsonb разбирает его при записи и хранит в двоичном виде.
Отсюда преимущества jsonb:
- индексы: по нему строится GIN-индекс, и запросы с операторами вхождения и существования ключа работают быстро. По
jsonиндексировать можно только выражение, то есть заранее выбранный путь; - скорость чтения: документ уже разобран, поэтому обращение к полю не требует парсинга текста при каждом запросе;
- богатый набор операторов:
@>,?,#>, обновление черезjsonb_set, слияние оператором||, работа с путями черезjsonpath; - нормализованное представление: дубликаты ключей схлопываются, пробелы убираются, числа приводятся к типу базы.
create index on events using gin (payload jsonb_path_ops);
select * from events where payload @> '{"type": "signup"}';Цена: запись немного дороже (нужен разбор и упаковка), а исходное форматирование теряется. Порядок ключей и дубликаты не сохраняются, поэтому если документ обязан вернуться байт в байт таким же, например при хранении подписанного тела запроса или ответа внешней системы, берут json.
Полезно добавить общий совет: jsonb подходит для действительно неструктурированной части данных, но поля, по которым идут фильтры и соединения, лучше выносить в обычные колонки. Полностью «схемалесс» таблица в реляционной базе быстро становится неудобной.
Где спотыкаются
Считают, что индекс по jsonb покрывает любые запросы. GIN помогает вхождению и существованию ключа, а для сравнения по конкретному пути нужен индекс по выражению.
Хранят в JSON всё подряд, включая идентификаторы связей, и теряют возможность нормальных соединений и ограничений целостности.
Не знают про jsonb_path_ops, который заметно компактнее обычного GIN, если нужен только оператор вхождения.