У PostgreSQL багато розробників стикаються з вибором: яку структуру даних юзати для зберігання інфи? Використовувати масиви (ARRAY) для простішої структури? Чи текстові (TEXT) колонки для рядків? А може, HSTORE для зберігання пар "ключ-значення"? Ну і, звісно, виникає питання: а коли все ж краще JSON або JSONB?
Щоб допомогти тобі розібратись у цьому, поговоримо про плюси і мінуси кожного підходу, а також покажемо приклади їх використання.
Коли юзати масиви (ARRAY), а коли JSONB?
Масиви (ARRAY) ідеально підходять для даних, які є однорідними наборами значень. Наприклад, якщо у тебе є список оцінок студентів або теги для запису, масиви — саме те.
Приклад масиву:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- масив оцінок
);
INSERT INTO students (name, grades)
VALUES ('Аліса', ARRAY[90, 85, 88]),
('Боб', ARRAY[70, 75, 78]);
З іншого боку, JSONB підходить для складніших, вкладених структур. Якщо ти хочеш зберігати додаткову інфу для кожного запису, наприклад, опис кожної оцінки, підійде JSONB.
Приклад JSONB:
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- об'єкт з даними про оцінки
);
INSERT INTO students_json (name, grades)
VALUES ('Аліса', '{"Математика": 90, "Наука": 85, "Англійська": 88}'),
('Боб', '{"Математика": 70, "Наука": 75, "Англійська": 78}');
Основні відмінності
| Критерій | Масиви (ARRAY) |
JSONB |
|---|---|---|
| Структура | Однорідні дані одного типу | Складні вкладені структури даних |
| Доступ до даних | За індексом: grades[1] |
За ключем: grades->'Математика' |
| Підтримка індексів | Тільки GIN або BTREE для всього масиву |
Зручні GIN і BTREE індекси по ключах |
| Коли використовувати | Прості списки даних (теги, оцінки, ідентифікатори) | Складні об'єкти з ключами і значеннями |
Приклади перетворення з масиву в JSONB і навпаки
Давай подивимось, як можна перетворювати дані між масивами і JSONB:
Масив → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- Результат:
-- [{"90","85","88"}]
JSONB → Масив
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- Результат:
-- {90,85,88}
Порівняння JSONB і текстових даних (TEXT)
Текстові колонки ідеальні, якщо треба просто зберігати рядки тексту або невеликі неструктуровані дані. Якщо твоя задача — пошук по співпадінню рядків, наприклад, у назві продукту чи описі, TEXT — твій вибір.
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('Основи SQL', 'Короткий вступ до SQL'),
('Поглиблений PostgreSQL', 'Детальний гайд по продуктивності PostgreSQL');
Коли краще юзати JSONB?
Якщо твій рядок перетворюється на інфу з вкладеною структурою (наприклад, опис з вкладеною категорією і списком тегів), краще обирати JSONB.
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "Основи SQL", "tags": ["початківець", "база даних"]}'),
('{"title": "Поглиблений PostgreSQL", "tags": ["продуктивність", "оптимізація"]}');
Основні відмінності
| Критерій | Текст (TEXT) |
JSONB |
|---|---|---|
| Структура | Неструктуровані дані | Структуровані, вкладені дані |
| Пошук | Повнотекстовий пошук | Пошук по ключах, значеннях, вкладеній структурі |
| Зміна даних | Тільки повна заміна | Зміна окремих ключів |
| Коли використовувати | Прості рядки тексту | Складні дані у форматі ключ-значення |
Порівняння JSONB і HSTORE
HSTORE — це старший брат JSONB, який дозволяє зберігати пари "ключ-значення". Наприклад, якщо твоя структура даних проста (не треба вкладеності і масивів), HSTORE буде легшим і швидшим.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"колір"=>"червоний", "розмір"=>"M"'),
('"колір"=>"синій", "розмір"=>"L"');
Чому JSONB замінив HSTORE?
Хоч HSTORE зручний для пар "ключ-значення", він не підтримує вкладеність і масиви, що робить JSONB більш універсальним. Якщо ти виріс із простих об'єктів, JSONB стає природним наступним кроком.
Основні відмінності
| Критерій | HSTORE | JSONB |
|---|---|---|
| Структура | Пари "ключ-значення", без вкладеності | Повноцінні вкладені структури |
| Підтримка масиву | Ні | Так |
| Пошук | Тільки по ключу | По ключах, значеннях, вкладеній структурі |
| Коли використовувати | Прості ключ-значення | Складні структури даних |
Як обрати підходящий тип даних?
Якщо у тебе:
- Проста структура — списки або однорідні дані, юзай масиви (
ARRAY). - Прості рядки або описи, юзай текстові колонки (
TEXT). - Пари "ключ-значення" без вкладеності, обирай
HSTORE. - Вкладені об'єкти і масиви, складна структура даних — тобі потрібен JSONB.
Приклади перетворення між форматами
TEXT → JSONB
SELECT to_jsonb('Простий приклад тексту') AS jsonb_form;
-- Результат: "Простий приклад тексту"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- Результат: {"title": "Основи SQL", "tags": ["початківець", "база даних"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- Результат: {"колір": "червоний", "розмір": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"колір": "червоний", "розмір": "M"}') AS hstore_form;
-- Результат: "колір"=>"червоний", "розмір"=>"M"
На що звернути увагу?
Якщо потрібна максимальна гнучкість і підтримка складних структур, обирай JSONB. Але якщо твоя задача — це прості структури даних, такі як масиви, текст або пари "ключ-значення", юзай відповідні типи даних (ARRAY, TEXT, HSTORE).
Не забувай, що правильний вибір структури даних допоможе уникнути головного болю на наступних етапах розробки і підвищить продуктивність твоїх запитів.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ