W PostgreSQL wielu devów zastanawia się: jaką strukturę danych wybrać do przechowywania info? Użyć tablic (ARRAY) do prostszych struktur? A może kolumn tekstowych (TEXT) do stringów? Albo HSTORE do przechowywania par "klucz-wartość"? No i oczywiście pojawia się pytanie: kiedy jednak lepiej postawić na JSON albo JSONB?
Żeby ci to rozjaśnić, pogadamy o plusach i minusach każdego podejścia, a także pokażemy przykłady ich użycia.
Kiedy używać tablic (ARRAY), a kiedy JSONB?
Tablice (ARRAY) są super do danych, które są jednorodnymi zestawami wartości. Na przykład, jeśli masz listę ocen studentów albo tagów do wpisu, tablice sprawdzą się idealnie.
Przykład tablicy:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- tablica ocen
);
INSERT INTO students (name, grades)
VALUES ('Alice', ARRAY[90, 85, 88]),
('Bob', ARRAY[70, 75, 78]);
Z drugiej strony, JSONB nadaje się do bardziej złożonych, zagnieżdżonych struktur. Jeśli chcesz trzymać dodatkowe dane dla każdego wpisu, np. opis każdej oceny, JSONB będzie spoko wyborem.
Przykład JSONB:
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- obiekt z danymi o ocenach
);
INSERT INTO students_json (name, grades)
VALUES ('Alice', '{"Matematyka": 90, "Nauka": 85, "Angielski": 88}'),
('Bob', '{"Matematyka": 70, "Nauka": 75, "Angielski": 78}');
Główne różnice
| Kryterium | Tablice (ARRAY) |
JSONB |
|---|---|---|
| Struktura | Jednorodne dane jednego typu | Złożone, zagnieżdżone struktury danych |
| Dostęp do danych | Po indeksie: grades[1] |
Po kluczu: grades->'Matematyka' |
| Wsparcie indeksów | Tylko GIN albo BTREE dla całej tablicy |
Wygodne GIN i BTREE po kluczach |
| Kiedy używać | Proste listy danych (tagi, oceny, identyfikatory) | Złożone obiekty z kluczami i wartościami |
Przykłady konwersji z tablicy do JSONB i odwrotnie
Zobaczmy, jak można konwertować dane między tablicami a JSONB:
Tablica → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- Wynik:
-- [{"90","85","88"}]
JSONB → Tablica
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- Wynik:
-- {90,85,88}
Porównanie JSONB i danych tekstowych (TEXT)
Kolumny tekstowe są idealne, jeśli chcesz po prostu przechowywać stringi albo małe niestrukturalne dane. Jeśli twoim celem jest wyszukiwanie po dopasowaniu tekstu, np. w nazwie produktu albo opisie, TEXT to twój wybór.
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('Podstawy SQL', 'Krótkie wprowadzenie do SQL'),
('Zaawansowany PostgreSQL', 'Dogłębny przewodnik po wydajności PostgreSQL');
Kiedy lepiej użyć JSONB?
Jeśli twój string zamienia się w info ze złożoną strukturą (np. opis z kategorią i listą tagów), lepiej wybrać JSONB.
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "Podstawy SQL", "tags": ["początkujący", "baza danych"]}'),
('{"title": "Zaawansowany PostgreSQL", "tags": ["wydajność", "optymalizacja"]}');
Główne różnice
| Kryterium | Tekst (TEXT) |
JSONB |
|---|---|---|
| Struktura | Niestrukturalne dane | Strukturalne, zagnieżdżone dane |
| Wyszukiwanie | Pełnotekstowe wyszukiwanie | Wyszukiwanie po kluczach, wartościach, strukturze |
| Zmiana danych | Tylko pełna zamiana | Zmiana pojedynczych kluczy |
| Kiedy używać | Proste stringi tekstowe | Złożone dane w formacie klucz-wartość |
Porównanie JSONB i HSTORE
HSTORE to taki starszy brat JSONB, który pozwala trzymać pary "klucz-wartość". Jeśli twoja struktura danych jest prosta (nie potrzebujesz zagnieżdżeń i tablic), HSTORE będzie lżejszy i szybszy.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"kolor"=>"czerwony", "rozmiar"=>"M"'),
('"kolor"=>"niebieski", "rozmiar"=>"L"');
Dlaczego JSONB wyparł HSTORE?
Mimo że HSTORE jest wygodny do par "klucz-wartość", nie obsługuje zagnieżdżeń i tablic, co sprawia, że JSONB jest bardziej uniwersalny. Jeśli wyrosłeś już z prostych obiektów, JSONB to naturalny kolejny krok.
Główne różnice
| Kryterium | HSTORE | JSONB |
|---|---|---|
| Struktura | Pary "klucz-wartość", bez zagnieżdżeń | Pełne zagnieżdżone struktury |
| Wsparcie tablic | Nie | Tak |
| Wyszukiwanie | Tylko po kluczu | Po kluczach, wartościach, strukturze |
| Kiedy używać | Proste klucz-wartość | Złożone struktury danych |
Jak wybrać odpowiedni typ danych?
Jeśli masz:
- Prosta struktura — listy albo jednorodne dane, użyj tablic (
ARRAY). - Proste stringi lub opisy, użyj kolumn tekstowych (
TEXT). - Pary "klucz-wartość" bez zagnieżdżeń, wybierz
HSTORE. - Zagnieżdżone obiekty i tablice, złożona struktura danych — potrzebujesz JSONB.
Przykłady konwersji między formatami
TEXT → JSONB
SELECT to_jsonb('Prosty przykład tekstu') AS jsonb_form;
-- Wynik: "Prosty przykład tekstu"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- Wynik: {"title": "Podstawy SQL", "tags": ["początkujący", "baza danych"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- Wynik: {"kolor": "czerwony", "rozmiar": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"kolor": "czerwony", "rozmiar": "M"}') AS hstore_form;
-- Wynik: "kolor"=>"czerwony", "rozmiar"=>"M"
Na co zwrócić uwagę?
Jeśli potrzebujesz maksymalnej elastyczności i wsparcia dla złożonych struktur, wybierz JSONB. Ale jeśli twoje zadanie to proste struktury danych, jak tablice, tekst czy pary "klucz-wartość", używaj odpowiednich typów danych (ARRAY, TEXT, HSTORE).
Pamiętaj, że dobry wybór struktury danych pozwoli ci uniknąć bólu głowy na późniejszych etapach developmentu i poprawi wydajność twoich zapytań.
GO TO FULL VERSION