Dans PostgreSQL, pas mal de devs se demandent : quelle structure de données utiliser pour stocker les infos ? Prendre des tableaux (ARRAY) pour une structure plus simple ? Ou alors des colonnes texte (TEXT) pour des chaînes ? Peut-être même HSTORE pour stocker des paires « clé-valeur » ? Et bien sûr, la question se pose : quand est-ce que JSON ou JSONB est le meilleur choix ?
Pour t'aider à t'y retrouver, on va parler des avantages et inconvénients de chaque approche, avec des exemples concrets d'utilisation.
Quand utiliser les tableaux (ARRAY) et quand JSONB ?
Les tableaux (ARRAY) sont parfaits pour des données qui sont des ensembles homogènes de valeurs. Par exemple, si tu as une liste de notes d'étudiants ou des tags pour un enregistrement, les tableaux sont nickel.
Exemple de tableau :
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- tableau de notes
);
INSERT INTO students (name, grades)
VALUES ('Alice', ARRAY[90, 85, 88]),
('Bob', ARRAY[70, 75, 78]);
De l'autre côté, JSONB est fait pour des structures plus complexes et imbriquées. Si tu veux stocker des infos supplémentaires pour chaque enregistrement, genre une description pour chaque note, JSONB est ce qu'il te faut.
Exemple JSONB :
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- objet avec les infos sur les notes
);
INSERT INTO students_json (name, grades)
VALUES ('Alice', '{"Math": 90, "Science": 85, "English": 88}'),
('Bob', '{"Math": 70, "Science": 75, "English": 78}');
Principales différences
| Critère | Tableaux (ARRAY) |
JSONB |
|---|---|---|
| Structure | Données homogènes d'un seul type | Structures de données imbriquées et complexes |
| Accès aux données | Par index : grades[1] |
Par clé : grades->'Math' |
| Support des index | Seulement GIN ou BTREE pour le tableau entier |
Index GIN et BTREE pratiques sur les clés |
| Quand utiliser | Listes simples de données (tags, notes, identifiants) | Objets complexes avec clés et valeurs |
Exemples de conversion entre tableau et JSONB
Voyons comment on peut convertir les données entre tableaux et JSONB :
Tableau → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- Résultat :
-- [{"90","85","88"}]
JSONB → Tableau
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- Résultat :
-- {90,85,88}
Comparaison JSONB et données texte (TEXT)
Les colonnes texte sont idéales si tu veux juste stocker des chaînes de caractères ou des petites données non structurées. Si ton besoin c'est de faire des recherches sur des correspondances de chaînes, genre dans le nom d'un produit ou une description, TEXT est fait pour toi.
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('SQL Basics', 'Une introduction concise à SQL'),
('Advanced PostgreSQL', 'Un guide approfondi sur la performance PostgreSQL');
Quand vaut-il mieux utiliser JSONB ?
Si ta chaîne devient une info avec une structure imbriquée (genre une description avec une catégorie imbriquée et une liste de tags), mieux vaut prendre JSONB.
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "SQL Basics", "tags": ["débutant", "base de données"]}'),
('{"title": "Advanced PostgreSQL", "tags": ["performance", "optimisation"]}');
Principales différences
| Critère | Texte (TEXT) |
JSONB |
|---|---|---|
| Structure | Données non structurées | Données structurées et imbriquées |
| Recherche | Recherche plein texte | Recherche sur les clés, valeurs, structure imbriquée |
| Modification des données | Seulement remplacement complet | Modification de clés individuelles |
| Quand utiliser | Chaînes de texte simples | Données complexes au format clé-valeur |
Comparaison JSONB et HSTORE
HSTORE — c'est le grand frère de JSONB, qui permet de stocker des paires « clé-valeur ». Par exemple, si ta structure de données est simple (pas besoin d'imbrication ni de tableaux), HSTORE sera plus léger et plus rapide.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"couleur"=>"rouge", "taille"=>"M"'),
('"couleur"=>"bleu", "taille"=>"L"');
Pourquoi JSONB a remplacé HSTORE ?
Même si HSTORE est pratique pour les paires « clé-valeur », il ne gère pas l'imbrication ni les tableaux, ce qui rend JSONB beaucoup plus polyvalent. Si tu dépasses les objets simples, JSONB devient la suite logique.
Principales différences
| Critère | HSTORE | JSONB |
|---|---|---|
| Structure | Paires « clé-valeur », sans imbrication | Structures imbriquées complètes |
| Support des tableaux | Non | Oui |
| Recherche | Seulement par clé | Par clés, valeurs, structure imbriquée |
| Quand utiliser | Clé-valeur simples | Structures de données complexes |
Comment choisir le bon type de données ?
Si tu as :
- Une structure simple — listes ou données homogènes, utilise tableaux (
ARRAY). - Des chaînes ou descriptions simples, prends colonnes texte (
TEXT). - Des paires « clé-valeur » sans imbrication, choisis
HSTORE. - Des objets imbriqués et des tableaux, structure complexe — il te faut JSONB.
Exemples de conversion entre formats
TEXT → JSONB
SELECT to_jsonb('Exemple de texte simple') AS jsonb_form;
-- Résultat : "Exemple de texte simple"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- Résultat : {"title": "SQL Basics", "tags": ["débutant", "base de données"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- Résultat : {"couleur": "rouge", "taille": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"couleur": "rouge", "taille": "M"}') AS hstore_form;
-- Résultat : "couleur"=>"rouge", "taille"=>"M"
À quoi faire gaffe ?
Si tu veux un max de flexibilité et le support des structures complexes, prends JSONB. Mais si ton besoin c'est des structures simples, genre tableaux, texte ou paires « clé-valeur », utilise les types de données adaptés (ARRAY, TEXT, HSTORE).
N'oublie pas : bien choisir ta structure de données t'évitera des prises de tête plus tard dans le dev et boostera les perfs de tes requêtes.
GO TO FULL VERSION