В чем преимущества JSONB над JSON в базе данных?
Что проверяют
Понимаете ли вы, как PostgreSQL хранит оба типа и что из этого следует для индексов и запросов. Следом обычно спрашивают, какой индекс вы построили бы под поиск по JSON-полю и как маппите jsonb в Java-сущность.
Как отвечать
json хранит точную копию текста и разбирает его при каждом обращении. jsonb разбирает документ один раз при записи и хранит бинарное представление. Отсюда различия:
- скорость: запросы к
jsonbбыстрее, документ не парсится заново. Запись чуть медленнее из-за разбора на входе; - индексы: GIN есть только у
jsonb. Классjsonb_ops(по умолчанию) обслуживает@>,?,?|,?&, аjsonb_path_opsкомпактнее и быстрее, но работает лишь для@>,@?и@@. Индекс по выражению вроде((data->>'status'))строится и дляjson; - операции: проверка вложенности
@>, наличия ключа?, изменение черезjsonb_setи||, удаление ключа через-, обращениеdata['key']с PostgreSQL 14; - сравнение: у
jsonbесть равенство, поэтому работаютDISTINCT,GROUP BYи уникальный индекс. Уjsonоператора равенства нет; - нормализация:
jsonbне хранит пробелы и порядок ключей, из дублирующихся ключей оставляет последний.
json уместен, когда документ нужен байт в байт: сырой вебхук для проверки подписи, журнал входящих запросов.
Со стороны Java: в Hibernate 6 поле размечают @JdbcTypeCode(SqlTypes.JSON), на PostgreSQL оно ляжет в jsonb. В голом JDBC строку передают через setObject(i, json, Types.OTHER) или приведение ?::jsonb, иначе драйвер отправит varchar и база откажет в неявном приведении.
Где спотыкаются
Говорят, что jsonb_set меняет одно поле на месте. Любое обновление пишет новую версию строки с документом целиком, поэтому большие документы, которые часто правят по одному полю, в jsonb обходятся дорого.
Утверждают, что jsonb всегда компактнее. На диске он нередко занимает столько же, сколько текст, или больше.
Прячут в jsonb поля, по которым постоянно фильтруют и джойнят. У планировщика нет статистики по ключам внутри документа, оценки строк получаются грубыми, и обычная колонка тут надёжнее.