Сьогодні перед нами стоїть задача глибше зрозуміти масиви і також більш детально порівняти їх із JSONB, розглянути їхні сильні та слабкі сторони і вибрати кращі практики для їх використання в реальних задачах.
Масиви vs JSONB: міні-черепашки даних vs гнучкість у коробці
Ти вже добре знаєш, що в масивах PostgreSQL можна зберігати значення будь-якого одного типу даних: масив чисел, стрічок або дат. Приклад: список оцінок студента, де всі елементи — числа.
-- Таблиця зі студентами та їх оцінками
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- масив оцінок
);
JSONB, на відміну від масиву, — це зберігання даних у вигляді JSON-структури. Це дуже схоже на знайомий усім JavaScript-об'єкт, але з перевагою швидкого парсингу та індексації. В JSONB можна зберігати як впорядковані списки, так і об'єкти з ключами та значеннями.
-- Таблиця зі студентами та різними даними про них
CREATE TABLE students_details (
id SERIAL PRIMARY KEY,
name TEXT,
details JSONB -- гнучка JSON-структура
);
Приклад даних у JSONB:
{
"grades": [90, 82, 77],
"address": {
"city": "Berlin",
"zip": "352912"
}
}
Отже, масиви — це спрощений спосіб роботи зі списками значень, а JSONB дає набагато більше можливостей для складних даних.
Основні відмінності між масивами і JSONB
| Ознака | Масиви | JSONB |
|---|---|---|
| Тип структури | Лінійна структура даних | Ієрархічна структура даних |
| Типи елементів | Тільки один тип даних | Різні типи даних |
| Розмір структури | Фіксований (лінійний) | Гнучкий, може містити списки і об'єкти |
| Швидкість доступу | Висока при фіксованих даних | Повільніше при складних пошуках |
| Індексація | Добре підтримує індексацію | Потребує індексації типу GIN |
| Застосування | Простий список або масив значень | Складні дані: вкладені об'єкти/лісти |
Тепер подивимось, як це все працює на практиці.
Коли використовувати масиви?
Припустимо, у нас є база даних з книжками, де кожна книжка може належати до кількох жанрів. Масив тут буде класним вибором.
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
genres TEXT[] -- масив жанрів
);
-- Приклад вставки книжки з кількома жанрами
INSERT INTO books (title, genres)
VALUES ('1984', ARRAY['Dystopia', 'Political Fiction', 'Science Fiction']);
Масиви круті, якщо ти впевнений, що:
- твої дані можна чітко зберігати як список,
- списки будуть невеликими і однотипними (наприклад, стрічки або числа),
- тобі треба просто зберігати і витягати списки (без складних операцій).
Переваги масивів
- Простота зберігання однотипних даних.
- Зручно для невеликих списків, таких як теги, категорії чи оцінки.
Коли використовувати JSONB?
Тепер уяви, що ти хочеш зберігати складніші дані про книжки, включаючи жанри, ISBN і рейтинг. Тут масиви вже не підходять — час для JSONB.
CREATE TABLE books_details (
id SERIAL PRIMARY KEY,
title TEXT,
details JSONB -- деталі книжки у вигляді JSONB
);
-- Приклад вставки складної інформації про книжку
INSERT INTO books_details (title, details)
VALUES (
'1984',
'{"genres": ["Dystopia", "Political Fiction", "Science Fiction"],
"isbn": "9780451524935",
"rating": 8.9}'
);
JSONB крутий, якщо тобі треба:
- зберігати складні чи різнорідні дані (числа, стрічки, списки, об'єкти),
- динамічно додавати параметри без зміни структури таблиці,
- зберігати вкладені дані (наприклад, адреси, характеристики, налаштування).
Переваги JSONB
- Висока гнучкість. Можна додавати нові ключі і значення без зміни структури таблиці.
- Підходить для зберігання складних даних, наприклад, JSON-відповідей API.
Вибір між масивами і JSONB
Якщо треба зберігати тільки списки однотипних даних — юзай масиви. Наприклад:
-- Зберігання ID учасників івентів
CREATE TABLE events (
id SERIAL PRIMARY KEY,
participant_ids INTEGER[]
);
Якщо дані різнорідні чи складні — краще використовувати JSONB. Наприклад:
-- Зберігання інформації про клієнтів з адресами
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
info JSONB
);
Під індексацію масиви і JSONB мають різні підходи. Для масивів частіше використовують GIN індекси, а для JSONB — GIN і BTREE, залежно від структури даних.
Продуктивність
Масиви обробляються швидше при типових задачах пошуку. JSONB трохи повільніше, але виграє у гнучкості. Якщо ти хочеш просто шукати елементи (наприклад, жанри чи ID), масиви будуть швидші:
-- Використання масивів з індексом GIN
CREATE INDEX idx_genres ON books USING GIN(genres);
-- Фільтрація книжок за жанром
SELECT * FROM books WHERE genres @> ARRAY['Science Fiction'];
Перевірка наявності даних
У JSONB більше можливостей з фільтрацією по ключах:
-- Перевірка наявності ключа "genres"
SELECT * FROM books_details WHERE details ? 'genres';
-- Перевірка наявності елемента у списку
SELECT * FROM books_details WHERE details->'genres' ?| ARRAY['Fantasy', 'Dystopia'];
Масиви дозволяють шукати значення напряму:
-- Перевірка наявності елемента у масиві
SELECT * FROM books WHERE genres @> ARRAY['Fantasy'];
Гнучкість структур
JSONB буде незамінним, якщо дані мають складні вкладені структури:
{
"genres": ["Fantasy", "Adventure"],
"ratings": {"goodreads": 8.5, "amazon": 4.7}
}
Для масивів це буде недосяжно без нормалізації чи додаткових полів.
В результаті, масиви і JSONB — це не конкуренти, а інструменти для різних задач. Якщо дані схожі на список — юзай масиви. Якщо ж у тебе складні, вкладені чи різнорідні дані — сміливо бери JSONB. Головне — пам'ятай про продуктивність і індексацію!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ