Одно из ключевых различий между JSON и JSONB заключается в формате хранения данных. JSON сохраняет данные в виде текста, а JSONB — в бинарной форме. Это означает, что:
- JSON сохраняет данные в том же виде, в котором вы их передали. Например, если вы вставляете строку
{"title": "PostgreSQL", "tags": ["database", "SQL"]}, она будет сохранена как есть. - JSONB сначала парсит JSON-объект, удаляет ненужные пробелы, упорядочивает ключи, оптимизирует структуру и только потом сохраняет её в бинарном формате.
Эта оптимизация позволяет JSONB быстрее работать с данными, особенно при выполнении сложных запросов на фильтрацию, поиск и сортировку.
Производительность операций чтения и записи
JSON и JSONB имеют разные характеристики по скорости чтения и записи данных:
- JSON быстрее записывается в базу, так как нет необходимости парсить данные перед сохранением. Однако чтение и обработка таких данных обычно медленнее, так как PostgreSQL во время выполнения запросов должен заново парсить данные.
- JSONB требует больше времени на запись, потому что перед сохранением данные проходят обработку. Однако чтение данных, их фильтрация и извлечение значений происходят гораздо быстрее, что делает JSONB предпочтительным для аналитических или поисковых задач.
Пример для наглядности:
-- Создание таблиц с JSON и JSONB
CREATE TABLE json_example (data JSON);
CREATE TABLE jsonb_example (data JSONB);
-- Вставка данных
INSERT INTO json_example VALUES ('{"key": "value", "tags": ["json", "example"]}');
INSERT INTO jsonb_example VALUES ('{"key": "value", "tags": ["jsonb", "example"]}');
-- Фильтрация данных
SELECT * FROM json_example WHERE data->'key' = '"value"'; -- Медленнее
SELECT * FROM jsonb_example WHERE data->'key' = '"value"'; -- Быстрее
Индексация данных
Одним из самых больших преимуществ JSONB является поддержка индексации. PostgreSQL позволяет создавать индексы для JSONB-колонок, используя тип индекса GIN. Это значительно ускоряет поиск и фильтрацию данных.
Пример создания индекса:
-- Индекс на JSONB-колонке
CREATE INDEX idx_jsonb_tags ON jsonb_example USING gin (data->'tags');
JSON, напротив, не поддерживает индексацию, что делает его менее подходящим для сложных операций поиска и фильтрации.
Когда использовать JSON, а когда JSONB
JSON лучше всего подходит для ситуаций, когда:
- Вам нужно хранить данные в исходном виде, без изменений.
- Вы не планируете активно выполнять запросы для фильтрации, поиска или сортировки по JSON-данным.
- JSON-данные используются преимущественно для передачи другим системам или клиентам в неизменённой форме (например, отдавать фронтенду через API).
Пример:
-- Хранение JSON без анализа
CREATE TABLE api_responses (
id SERIAL PRIMARY KEY,
response JSON
);
-- Вставка данных, как они пришли от API
INSERT INTO api_responses (response)
VALUES ('{"status": "success", "payload": {"id": 123, "name": "John"}}');
JSONB стоит использовать, если:
- Вы планируете активно фильтровать, искать, группировать или сортировать данные по значениям внутри JSON.
- Производительность доступа к данным важнее производительности записи.
- Вы хотите использовать индексацию для ускорения операций с JSON-данными.
Пример:
-- Хранение JSONB для анализа и работы с вложенными объектами
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSONB
);
-- Вставка данных
INSERT INTO products (details)
VALUES ('{"name": "Laptop", "price": 1200, "tags": ["electronics", "computers"]}');
-- Поиск продуктов с тегом "electronics"
SELECT * FROM products
WHERE details @> '{"tags": ["electronics"]}';
Подробнее об операторе @> и --> вы узнаете в следующих лекциях :P
Примеры работы с JSON и JSONB
Создадим две таблицы: одну с JSON-колонкой, другую с JSONB:
CREATE TABLE json_table (
id SERIAL PRIMARY KEY,
data JSON
);
CREATE TABLE jsonb_table (
id SERIAL PRIMARY KEY,
data JSONB
);
Вставка данных будет одинаковой для обеих таблиц:
INSERT INTO json_table (data)
VALUES ('{"key": "value", "tags": ["json", "example"]}');
INSERT INTO jsonb_table (data)
VALUES ('{"key": "value", "tags": ["jsonb", "example"]}');
Теперь попробуем извлечь данные, где ключ key имеет значение value:
-- Для JSON
SELECT * FROM json_table
WHERE data->>'key' = 'value';
-- Для JSONB
SELECT * FROM jsonb_table
WHERE data->>'key' = 'value';
Для небольших объёмов данных разница в производительности будет практически незаметной. Однако при работе с миллионами строк JSONB покажет значительно лучшие результаты, особенно если вы создадите индекс:
CREATE INDEX idx_jsonb_key ON jsonb_table USING gin ((data->>'key'));
Работа с вложенными объектами и массивами также более эффективна в JSONB:
-- Извлечение значения из массива
SELECT data->'tags'->>0 AS first_tag
FROM jsonb_table;
Преимущества и недостатки
| Особенность | JSON | JSONB |
|---|---|---|
| Хранение данных | Сохраняет данные в исходном текстовом формате | Сохраняет данные в бинарном формате, упорядочивая ключи |
| Производительность записи | Быстрее, так как сохраняются "как есть" | Медленнее из-за предварительного парсинга |
| Производительность чтения | Медленнее, так как данные нужно парсить в момент выполнения запроса | Быстрее, так как данные уже оптимизированы для чтения |
| Индексация | Не поддерживается | Поддерживается (индексы GIN, BTREE) |
| Фильтрация | Медленная | Быстрая |
| Поддержка операций | Ограниченная | Расширенная |
Выбор между JSON и JSONB зависит от характера задачи. Если нужно просто хранить данные в неизменном текстовом виде, смело выбирайте JSON. Если же вы планируете активно работать с данными внутри колонок, выполнять фильтрацию, поиск или группировку, JSONB будет более производительным и удобным выбором.
Для сложных приложений, где JSON-данные являются не просто "хранилищем", но и активно используются в аналитике, JSONB станет незаменимым инструментом. Так что, если сомневаетесь — выбирайте JSONB. Возможно, ваш будущий "самый быстрый запрос всей жизни" скажет вам за это спасибо!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ