PostgreSQL 45 termes

45 termes affichés

TypeCLI Concept DataStructure Method Pattern Security Tool
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Mis à jour ces 90 derniers jours 10 nouvelles · 20 révisées

Advisory Locks

PostgreSQL 🔴 Senior? entretien

Verrous coopératifs applicatifs gères par PostgreSQL. Contrairement aux verrous de table, ils n'ont de sens que pour l'application qui les utilise. Peuvent être session-level ou transaction-level.

Un panneau 'Occupe' sur une cabine : c'est l'application qui le respecte, pas la base qui bloque.

-- Verrou au niveau session
SELECT pg_advisory_lock(42);
-- ... logique exclusive ...
SELECT pg_advisory_unlock(42);

Cas d'usage : Éviter les exécutions concurrentes de cron jobs ou de migrations sur la même ressource logique.

#sgbd#interview#database#postgresql

Array Type

PostgreSQL 🟡 Mid? entretien

PostgreSQL supporte nativement les colonnes de type tableau. Permet de stocker plusieurs valeurs du même type dans une seule colonne, avec des opérateurs dedies (@>, &&, ANY).

Une cellule Excel qui peut contenir une liste de valeurs au lieu d'une seule.

CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  tags TEXT[] DEFAULT '{}'
);
SELECT * FROM posts WHERE 'sql' = ANY(tags);
SELECT * FROM posts WHERE tags @> '{sql,pg}';

Cas d'usage : Stocker des tags, des permissions ou de petites listes sans créer une table de jointure.

Anti-pattern : Utiliser des arrays pour des relations complexes au lieu d'une table many-to-many.
#sgbd#interview#database#postgresql

Async I/O (io_method)

PostgreSQL 🔴 Senior? entretien

PostgreSQL 18 (25 septembre 2025) introduit un sous-système d'entrées/sorties asynchrones contrôle par le paramètre io_method, qui accélère les scans séquentiels, les bitmap heap scans et le VACUUM en regroupant les lectures disque via io_combine_limit et io_max_combine_limit.

Comme envoyer plusieurs coursiers chercher des colis en parallèle plutôt qu'un seul aller-retour a la fois.

# postgresql.conf
io_method = 'io_uring'   # ou 'worker', 'sync'
io_combine_limit = 16
io_max_combine_limit = 32

Cas d'usage : Accélérer les gros scans séquentiels et le VACUUM sur des tables volumineuses en I/O-bound.

Anti-pattern : Changer io_method en production sans benchmarker : le gain dépend fortement du système de fichiers et du stockage sous-jacent.
#sgbd#interview#database#postgresql#pg18

B-tree Index

PostgreSQL 🟡 Mid? entretien

Type d'index par défaut dans PostgreSQL. Structure en arbre équilibre optimisée pour les comparaisons d'égalité et de plage (<, >, BETWEEN, ORDER BY). PostgreSQL 18 (25 septembre 2025) ajoute le Skip Scan : un index multicolonne peut désormais être utilise même sans condition sur ses premières colonnes, la ou seul un scan complet était possible auparavant.

Un dictionnaire avec des onglets alphabétiques : tu trouves n'importe quel mot en quelques sauts.

CREATE INDEX idx_users_email
  ON users (email);
-- Equivalent a :
CREATE INDEX idx_users_email
  ON users USING btree (email);

Cas d'usage : Optimiser les requêtes de recherche, tri et filtrage sur des colonnes fréquemment interrogées.

#sgbd#interview#database#postgresql

BRIN Index

PostgreSQL 🔴 Senior? entretien

Block Range Index, index extrêmement compact qui stocke les min/max par bloc de pages. Idéal pour les colonnes naturellement ordonnées comme les timestamps.

Au lieu d'indexer chaque page d'un livre, noter juste 'pages 1-50 : chapitres A-C'.

CREATE INDEX idx_logs_time
  ON logs USING brin (created_at)
  WITH (pages_per_range = 128);

Cas d'usage : Indexer des tables de logs ou de séries temporelles avec des milliards de lignes et un index minuscule.

Anti-pattern : Utiliser BRIN sur des colonnes dont les valeurs ne sont pas corrélées a l'ordre physique des lignes.
#sgbd#interview#database#postgresql

CHECK Constraint

PostgreSQL 🟢 Junior? entretien

Contrainte qui vérifie qu'une condition booléenne est vraie pour chaque ligne. Peut référencer plusieurs colonnes de la même table.

Un videur qui vérifie ta carte d'identité : si tu as moins de 18 ans, tu ne rentres pas.

CREATE TABLE products (
  id SERIAL PRIMARY KEY,
  price NUMERIC CHECK (price > 0),
  discount NUMERIC CHECK (discount BETWEEN 0 AND 1)
);

Cas d'usage : Garantir les règles métier au niveau de la base : prix positif, âge minimum, stock non négatif.

#sgbd#interview#database#postgresql

Colonnes generees virtuelles

PostgreSQL 🟡 Mid? entretien

Depuis PostgreSQL 18 (25 septembre 2025), les colonnes générées (GENERATED ALWAYS AS) sont virtuelles par défaut : leur valeur est recalculee a la lecture plutôt que stockée sur disque a l'écriture. Le mot-clé STORED reste disponible pour retrouver l'ancien comportement quand le stockage physique est préféré.

Comme un total de facture recalcule a chaque affichage plutôt qu'imprime et fige des la création du document.

ALTER TABLE orders
  ADD COLUMN total_ttc numeric
  GENERATED ALWAYS AS (total_ht * 1.20) VIRTUAL;

-- Pour retrouver l'ancien comportement (stocke sur disque) :
-- GENERATED ALWAYS AS (total_ht * 1.20) STORED

Cas d'usage : Exposer un champ calcule (TTC, slug, total) sans payer le coût d'écriture ni le stockage disque a chaque insertion.

Anti-pattern : Migrer vers PG18 sans vérifier si du code s'appuyait implicitement sur le stockage physique des colonnes générées (par exemple un index dessus).
#sgbd#interview#database#postgresql#pg18

Covering Index (INCLUDE)

PostgreSQL 🔴 Senior? entretien

Index qui inclut des colonnes supplémentaires non-clé via INCLUDE. Permet un Index-Only Scan en fournissant toutes les colonnes nécessaires sans accéder a la table.

Un sommaire de livre qui inclut un résume de chaque chapitre : pas besoin de tourner les pages.

CREATE INDEX idx_orders_covering
  ON orders (user_id)
  INCLUDE (total, status);

Cas d'usage : Éliminer les accès table pour les requêtes fréquentes qui ne lisent que quelques colonnes.

#sgbd#interview#database#postgresql

CTE (WITH)

PostgreSQL 🟡 Mid? entretien

Common Table Expression : sous-requête nommée définie avec WITH, utilisable comme une table temporaire dans la requête principale. Peut être recursive pour les hiérarchies.

Définir une variable intermédiaire dans un calcul complexe pour le rendre lisible étape par étape.

WITH active_users AS (
  SELECT * FROM users WHERE status = 'active'
)
SELECT a.name, COUNT(o.id) as orders
FROM active_users a
JOIN orders o ON a.id = o.user_id
GROUP BY a.name;

Cas d'usage : Décomposer des requêtes complexes en étapes lisibles, ou parcourir des structures arborescentes avec CTE recursive.

#sgbd#interview#database#postgresql

Enum Type

PostgreSQL 🟢 Junior? entretien

Type personnalise définissant un ensemble fixe de valeurs autorisées. Plus performant et type-safe qu'une contrainte CHECK sur un VARCHAR.

Un menu déroulant avec des options figées : tu ne peux choisir que ce qui est propose.

CREATE TYPE mood AS ENUM (
  'happy', 'sad', 'neutral'
);
CREATE TABLE entries (
  id SERIAL PRIMARY KEY,
  feeling mood NOT NULL
);

Cas d'usage : Définir des statuts, roles ou catégories avec un nombre fini de valeurs connues a l'avance.

Anti-pattern : Créer un enum pour des valeurs qui changent souvent, car ajouter/supprimer des valeurs est lourd.
#sgbd#interview#database#postgresql

EXPLAIN / EXPLAIN ANALYZE

PostgreSQL 🟡 Mid? entretien

EXPLAIN montre le plan d'exécution prévu d'une requête. EXPLAIN ANALYZE exécuté réellement la requête et montre les temps réels. Essentiel pour l'optimisation.

EXPLAIN = le GPS qui te montre l'itinéraire prévu. EXPLAIN ANALYZE = le GPS avec le temps réel du trajet.

EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id)
FROM users u
JOIN orders o ON u.id = o.user_id
GROUP BY u.name;

Cas d'usage : Diagnostiquer les requêtes lentes, vérifier l'utilisation des index et optimiser les jointures.

Anti-pattern : Utiliser EXPLAIN ANALYZE sur une requête DELETE ou UPDATE sans transaction, les données sont réellement modifiées.
#sgbd#interview#database#postgresql

Expression Index

PostgreSQL 🟡 Mid? entretien

Index créé sur une expression ou une fonction plutôt que sur une colonne brute. Permet d'indexer des transformations comme LOWER(), des extractions de date ou des calculs.

Un index de livre qui classe les titres sans accents ni majuscules pour une recherche simplifiée.

CREATE INDEX idx_users_lower_email
  ON users (LOWER(email));
-- La requete doit utiliser la meme expression
SELECT * FROM users
  WHERE LOWER(email) = '[email protected]';

Cas d'usage : Optimiser les recherches case-insensitive ou les filtres sur des champs transformes.

#sgbd#interview#database#postgresql

FOREIGN KEY

PostgreSQL 🟢 Junior

Contrainte referentielle qui garantit qu'une valeur dans une table existe dans la table référence. Supporte ON DELETE CASCADE, SET NULL et RESTRICT.

Un lien hypertexte garanti : il est impossible de pointer vers une page qui n'existe pas.

CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  user_id INT NOT NULL
    REFERENCES users(id)
    ON DELETE CASCADE
);

Cas d'usage : Maintenir l'intégrité referentielle entre les tables, comme les commandes liées aux utilisateurs.

Anti-pattern : Omettre les foreign keys pour 'gagner en perf', puis se retrouver avec des données orphelines.
#sgbd#interview#database#postgresql

GIN Index

PostgreSQL 🔴 Senior

Generalized Inverted Index, optimise pour les valeurs composites comme les arrays, JSONB et le full-text search. Indexe chaque élément individuel du contenu.

L'index d'un livre de recettes : chaque ingrédient pointe vers toutes les recettes qui l'utilisent.

CREATE INDEX idx_posts_tags
  ON posts USING gin (tags);
CREATE INDEX idx_events_data
  ON events USING gin (data jsonb_path_ops);

Cas d'usage : Accélérer les recherches dans des colonnes JSONB, des arrays ou du texte avec tsvector.

#sgbd#interview#database#postgresql

GiST Index

PostgreSQL 🔴 Senior

Generalized Search Tree, index polyvalent pour les données géométriques, les ranges et le full-text. Supporte les requêtes de proximité, d'inclusion et de chevauchement.

Un plan de quartier qui sait répondre a 'quels bâtiments sont dans ce périmètre ?'.

CREATE INDEX idx_locations
  ON places USING gist (location);
-- Avec PostGIS
SELECT * FROM places
  WHERE ST_DWithin(location, point, 1000);

Cas d'usage : Requêtes geospatiales avec PostGIS ou recherche dans des plages de valeurs (ranges).

#sgbd#interview#database#postgresql

Depuis PostgreSQL 17 (26 septembre 2024), pg_basebackup accepte l'option --incremental pour ne sauvegarder que les blocs modifies depuis une sauvegarde de référence, grâce a des fichiers de résume WAL (summarize_wal). pg_combinebackup reconstitue ensuite une sauvegarde complète a partir de la chaîne incrementale.

Comme ne photocopier que les pages modifiées d'un classeur plutôt que tout le classeur a chaque sauvegarde.

# Sauvegarde complete de reference
pg_basebackup -D /backup/full -Ft -X none

# Sauvegarde incrementale basee sur le manifest precedent
pg_basebackup -D /backup/incr1 \
  --incremental=/backup/full/backup_manifest

# Reconstitution complete
pg_combinebackup /backup/full /backup/incr1 -o /backup/restored

Cas d'usage : Réduire le temps et l'espace disque des sauvegardes quotidiennes sur une base volumineuse a faible taux de modification.

Anti-pattern : Activer --incremental sans avoir configure summarize_wal en amont : aucun fichier de résume n'existe pour calculer le delta.
#sgbd#interview#database#postgresql#pg17

JOIN (INNER, LEFT, RIGHT, FULL)

PostgreSQL 🟢 Junior

Opérations de jointure entre tables. INNER retourne les correspondances. LEFT garde toutes les lignes gauches. RIGHT garde toutes les lignes droites. FULL garde tout.

INNER = invites présents aux deux fêtes. LEFT = tous les invites de la fête A, avec ceux aussi a la fête B. FULL = tous les invites des deux fêtes.

SELECT u.name, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.total > 100;

Cas d'usage : Combiner des données de plusieurs tables pour des rapports, des APIs ou des dashboards.

Anti-pattern : Faire un CROSS JOIN involontaire en oubliant la clause ON, produisant un produit cartésien.
#sgbd#interview#database#postgresql

JSON_TABLE

PostgreSQL 🔴 Senior

Fonction SQL/JSON introduite dans PostgreSQL 17 (26 septembre 2024) qui transforme un document JSON en vue relationnelle exploitable dans une clause FROM. La clause COLUMNS définit le mapping de chaque chemin JSON vers une colonne typée, avec NESTED PATH pour extraire des niveaux imbriques.

Comme déplier une feuille pliée en accordéon (JSON imbrique) pour en faire un tableau plat lisible ligne par ligne.

SELECT jt.* FROM my_films,
  JSON_TABLE(js, '$.favorites[*]' COLUMNS (
    id FOR ORDINALITY,
    kind text PATH '$.kind',
    title text PATH '$.films[*].title' WITH WRAPPER
  )) AS jt;

Cas d'usage : Interroger un champ JSONB avec la même syntaxe qu'une table SQL classique, sans fonctions jsonb_* imbriquées.

Anti-pattern : Continuer a empiler jsonb_array_éléments() et jsonb_extract_path_text() alors que JSON_TABLE exprime la même logique en une seule clause lisible.
#sgbd#interview#database#postgresql#pg17

JSONB

PostgreSQL 🟡 Mid? entretien

Type de données binaire JSON dans PostgreSQL. Contrairement a JSON (texte brut), JSONB est parse et stocke en binaire, permettant l'indexation et les requêtes performantes.

JSON compile : tu perds la mise en forme originale mais tu gagnes la vitesse de recherche d'un index.

CREATE TABLE events (
  id SERIAL PRIMARY KEY,
  data JSONB NOT NULL
);
SELECT * FROM events
  WHERE data->>'type' = 'click'
  AND (data->'meta'->>'count')::int > 5;

Cas d'usage : Stocker des données semi-structurées (logs, config, metadonnees) dans une base relationnelle.

Anti-pattern : Utiliser JSONB pour tout au lieu de colonnes relationnelles, perdant les avantages du schema.
#sgbd#interview#database#postgresql

LATERAL JOIN

PostgreSQL 🔴 Senior

JOIN ou la sous-requête droite peut référencer des colonnes de la table gauche. Permet des sous-requêtes corrélées dans le FROM, comme un forEach SQL.

Pour chaque client, ouvrir son dossier et y chercher ses 3 dernières commandes.

SELECT u.name, recent.title
FROM users u
LATERAL (
  SELECT title FROM orders
  WHERE user_id = u.id
  ORDER BY created_at DESC
  LIMIT 3
) recent;

Cas d'usage : Récupérer les N derniers éléments par groupe sans window function complexe.

#sgbd#interview#database#postgresql

LISTEN / NOTIFY

PostgreSQL 🔴 Senior

Système de pub/sub intégré a PostgreSQL. LISTEN s'abonne a un canal, NOTIFY envoie un message. Permet la communication asynchrone entre processus sans polling.

Un talkie-walkie intégré a la base de données : un service parle, les autres écoûtent sur le même canal.

-- Session 1
LISTEN order_created;
-- Session 2
NOTIFY order_created, '{"id": 42}';
-- Session 1 recoit la notification

Cas d'usage : Notifier un service en temps réel quand une commande est créée, sans message broker externe.

#sgbd#interview#database#postgresql

Logical Replication Failover Slots

PostgreSQL 🔴 Senior

Depuis PostgreSQL 17 (26 septembre 2024), les slots de réplication logique peuvent être synchronises vers un standby physique via sync_réplication_slots, et l'utilitaire pg_createsubscriber créé un abonne logique a partir d'un standby physique. pg_upgrade préserve désormais aussi les slots et abonnements logiques existants.

Avant, basculer sur un standby faisait perdre la place ou en étaient les abonnes logiques, comme perdre le signet d'un livre au changement de bibliothécaire. Désormais le signet suit le changement.

# Sur le primaire
psql -c "ALTER SYSTEM SET sync_replication_slots = on;"

# Creer un abonne logique a partir d'un standby physique
pg_createsubscriber --pgdata=/var/lib/postgresql/standby \
  --publication=pub1 --subscription=sub1 \
  --database=app --socket-directory=/tmp

Cas d'usage : Basculer (failover) un primaire sans casser les abonnements de réplication logique en aval.

Anti-pattern : Promouvoir un standby physique en primaire sans sync_réplication_slots active : les consommateurs logiques perdent leur position.
#sgbd#interview#database#postgresql#pg17

MERGE

PostgreSQL 🔴 Senior

Commande introduite dans PostgreSQL 15 (2022) qui combine INSERT, UPDATE et DELETE en une seule instruction conditionnelle via des clauses WHEN MATCHED / WHEN NOT MATCHED. PostgreSQL 17 (26 septembre 2024) y ajoute WHEN NOT MATCHED BY SOURCE et le support de RETURNING avec la fonction merge_action().

Comme trier un stock en une seule passe : ce qui existe déjà est mis a jour, ce qui est nouveau est ajoute, ce qui a disparu est retire.

MERGE INTO stock s
USING deliveries d ON d.sku = s.sku
WHEN MATCHED THEN
  UPDATE SET qty = s.qty + d.qty
WHEN NOT MATCHED THEN
  INSERT (sku, qty) VALUES (d.sku, d.qty)
WHEN NOT MATCHED BY SOURCE THEN
  DELETE
RETURNING merge_action(), s.sku;

Cas d'usage : Synchroniser une table cible avec une source (upsert + suppression) en une seule requête atomique.

Anti-pattern : Utiliser MERGE sur une vue matérialisée ou une table distante (foreign table) : non supporte.
#sgbd#interview#database#postgresql#pg17

MVCC

PostgreSQL 🔴 Senior

Multi-Version Concurrency Control : mécanisme ou chaque transaction voit un snapshot cohérent de la base. Les lectures ne bloquent jamais les écritures et vice-versa.

Chaque client du restaurant reçoit sa propre copie du menu, même si le chef met a jour les plats en cuisine.

-- Transaction A lit des donnees
BEGIN;
SELECT * FROM accounts WHERE id = 1;
-- Transaction B modifie en parallele
-- A ne voit pas les changements de B
COMMIT;

Cas d'usage : Comprendre pourquoi PostgreSQL gère si bien la concurrence sans verrouillage pessimiste.

#sgbd#interview#database#postgresql

Partial Index

PostgreSQL 🟡 Mid? entretien

Index créé avec une clause WHERE qui n'indexe qu'un sous-ensemble des lignes de la table. Plus petit et plus rapide qu'un index complet.

Un annuaire qui ne liste que les médecins de garde, pas tous les médecins de la ville.

CREATE INDEX idx_active_users
  ON users (email)
  WHERE status = 'active';

Cas d'usage : Optimiser les requêtes qui filtrent toujours sur la même condition, comme les utilisateurs actifs.

#sgbd#interview#database#postgresql

Partitionnement declaratif

PostgreSQL 🔴 Senior? entretien

PostgreSQL découpé une table logique en plusieurs tables physiques (partitions) selon une stratégie RANGE, LIST ou HASH déclarée via PARTITION BY. Chaque partition se crée avec CREATE TABLE ... PARTITION OF, et le partition pruning éliminé automatiquement les partitions non concernées par une requête.

Comme classer des archives papier par année dans des cartons séparés plutôt que dans un seul immense classeur : on ne sort que le carton de l'année recherchée.

CREATE TABLE measurement (
  city_id int, logdate date, peaktemp int
) PARTITION BY RANGE (logdate);

CREATE TABLE measurement_y2026m01 PARTITION OF measurement
  FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');

Cas d'usage : Archiver ou purger de très grandes tables temporelles (logs, mesures) en droppant une partition entière en une opération instantanée.

Anti-pattern : Oublier d'inclure la colonne de partitionnement dans une contrainte UNIQUE/PRIMARY KEY : PostgreSQL l'exige.
#sgbd#interview#database#postgresql

pg_dump / pg_restore

PostgreSQL 🟢 Junior

pg_dump exporte une base en SQL ou en format custom. pg_restore réimporté un dump au format custom. Ensemble, ils permettent les backups et les migrations.

pg_dump = photocopier tous les dossiers du bureau. pg_restore = reclasser les photocopies dans un nouveau bureau.

pg_dump -Fc -U postgres mydb > backup.dump
pg_restore -U postgres -d newdb backup.dump

Cas d'usage : Sauvegarder une base avant une migration, cloner un environnement de production en staging.

Anti-pattern : Faire des dumps en texte SQL pour de grosses bases au lieu du format custom (-Fc), bien plus rapide a restaurer.
#sgbd#interview#database#postgresql

pg_stat_statements

PostgreSQL 🔴 Senior

Extension qui collecte les statistiques d'exécution de toutes les requêtes SQL : nombre d'appels, temps moyen, lignes retournées. Essentielle pour le monitoring en prod.

Un compteur de performances pour chaque requête, comme un tableau de bord de Formule 1.

CREATE EXTENSION pg_stat_statements;
SELECT query, calls, mean_exec_time,
  rows
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;

Cas d'usage : Identifier les requêtes les plus lentes ou les plus fréquentes pour optimiser la base en production.

#sgbd#interview#database#postgresql

pg_trgm

PostgreSQL 🟡 Mid? entretien

Extension qui fournit la recherche par similarité basée sur les trigrammes. Permet la recherche floue (fuzzy matching) et le LIKE/ILIKE rapide grâce aux index GIN ou GiST.

Un correcteur orthographique intégré a ta base de données : il trouve 'PostgreSQL' même si tu tapes 'Postgre'.

CREATE EXTENSION pg_trgm;
CREATE INDEX idx_trgm ON users
  USING gin (name gin_trgm_ops);
SELECT * FROM users
  WHERE name % 'Alic'
  ORDER BY similarity(name, 'Alic') DESC;

Cas d'usage : Implémenter une barre de recherche tolérante aux fautes de frappe sans Elasticsearch.

#sgbd#interview#database#postgresql

pgcrypto

PostgreSQL 🟡 Mid? entretien

Extension fournissant des fonctions de chiffrement : gen_random_uuid(), crypt() pour le hashing de mots de passe, pgp_sym_encrypt/decrypt pour le chiffrement symétrique.

Un coffre-fort intégré directement dans la base de données.

CREATE EXTENSION pgcrypto;
-- UUID
SELECT gen_random_uuid();
-- Hash password
SELECT crypt('password', gen_salt('bf'));

Cas d'usage : Générer des UUIDs ou hasher des mots de passe directement dans la base sans code applicatif.

Anti-pattern : Stocker des mots de passe en clair ou avec MD5 au lieu d'utiliser bcrypt via crypt().
#sgbd#interview#database#postgresql#security

pgvector + index HNSW

PostgreSQL 🔴 Senior

pgvector (version 0.8.6) est l'extension PostgreSQL de référence pour stocker des vecteurs (type vector, jusqu'a 16 000 dimensions) et effectuer des recherches par similarité. Son index HNSW (Hierarchical Navigable Small World) offre de meilleures performances de requête que l'index IVFFlat, au prix d'un temps de construction plus long.

HNSW construit un réseau de raccourcis a plusieurs échelles, comme un plan d'autoroutes puis de routes locales, pour rejoindre le point le plus proche plus vite qu'en parcourant la carte a plat (IVFFlat).

CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE items (
  id bigserial PRIMARY KEY,
  embedding vector(768)
);
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);

SELECT id FROM items
  ORDER BY embedding <=> '[0.1, 0.2]' LIMIT 5;

Cas d'usage : Recherche de similarité sémantique (RAG, recommandation) directement en SQL, sans base vectorielle dédiée séparée.

Anti-pattern : Construire un index HNSW sur une table qui reçoit encore des inserts massifs : privilégier IVFFlat en phase de chargement puis basculer vers HNSW.
#sgbd#interview#database#postgresql

PostGIS

PostgreSQL 🔴 Senior

Extension qui ajoute le support des données geospatiales a PostgreSQL. Fournit des types (geometry, geography), des fonctions (ST_Distance, ST_Contains) et des index spatiaux.

Transformer PostgreSQL en GPS intelligent capable de calculer des distances et des zones sur une carte.

CREATE EXTENSION postgis;
SELECT name FROM restaurants
WHERE ST_DWithin(
  location,
  ST_MakePoint(2.35, 48.86)::geography,
  1000
);

Cas d'usage : Applications de cartographie, calcul de zones de livraison ou analyse geospatiale.

#sgbd#interview#database#postgresql

PRIMARY KEY

PostgreSQL 🟢 Junior

Contrainte qui garantit l'unicité et la non-nullité d'une ou plusieurs colonnes. Créé automatiquement un index B-tree unique. Chaque table ne peut avoir qu'une seule PK.

Le numéro de sécurité sociale d'une ligne : unique, obligatoire et jamais vide.

CREATE TABLE users (
  id SERIAL PRIMARY KEY
);
-- Composite
CREATE TABLE order_items (
  order_id INT, product_id INT,
  PRIMARY KEY (order_id, product_id)
);

Cas d'usage : Identifier de manière unique chaque ligne d'une table.

#sgbd#interview#database#postgresql

psql

PostgreSQL 🟢 Junior

Client en ligne de commande officiel de PostgreSQL. Permet d'exécuter des requêtes SQL, d'administrer la base et d'utiliser des meta-commandes comme \dt, \d, \l.

Le terminal de commande de PostgreSQL, comme mongosh pour MongoDB.

psql -U postgres -d mydb
\dt          -- lister les tables
\d users     -- decrire une table
\conninfo    -- infos de connexion

Cas d'usage : Administrer et debugger une base PostgreSQL en ligne de commande.

#sgbd#interview#database#postgresql

Row Level Security (RLS)

PostgreSQL 🔴 Senior

Mécanisme qui restreint, ligne par ligne, les données visibles ou modifiables selon le role connecte, en complément des privilèges SQL classiques. Une fois ENABLE ROW LEVEL SECURITY active sur une table, aucune ligne n'est accessible tant qu'aucune CREATE POLICY explicite n'existe.

Comme donner a chaque locataire d'un immeuble une clé qui n'ouvre que sa propre porte, même s'ils partagent le même bâtiment (la même table).

ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON accounts
  USING (
    tenant_id = current_setting('app.current_tenant_id')::int
  )
  WITH CHECK (
    tenant_id = current_setting('app.current_tenant_id')::int
  );

Cas d'usage : Isoler les données de plusieurs clients (multi-tenant) dans une seule table partagée sans dupliquer la base.

Anti-pattern : Oublier que le propriétaire de la table et les superutilisateurs contournent RLS par défaut, sauf FORCE ROW LEVEL SECURITY.
#sgbd#interview#database#postgresql#security

Serial / UUID

PostgreSQL 🟢 Junior? entretien

SERIAL est un entier auto-incrémenté (1, 2, 3...). UUID est un identifiant unique universel de 128 bits, généralement génère aléatoirement (UUIDv4). PostgreSQL 18 (25 septembre 2025) ajoute la fonction native uuidv7(), qui encode un timestamp dans les premiers bits pour rester triable chronologiquement et limiter la fragmentation d'index que provoque UUIDv4.

SERIAL = numéro de ticket dans une file d'attente. UUID = numéro de passeport, unique dans le monde entier.

CREATE TABLE orders (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  seq SERIAL
);

Cas d'usage : UUID pour les systèmes distribues ou la sécurité. SERIAL pour la simplicité et la lisibilité.

Anti-pattern : Exposer des ids SERIAL dans les URLs publiques, permettant l'énumération des ressources.
#sgbd#interview#database#postgresql

Stored Procedures / Functions

PostgreSQL 🟡 Mid? entretien

Blocs de code PL/pgSQL stockes et exécutés cote serveur. Les fonctions retournent une valeur, les procédures (depuis PG 11) supportent les transactions internes.

Des macros Excel stockées dans le serveur : un appel déclenché toute la logique sans transfert de données.

CREATE FUNCTION get_user_orders(uid INT)
RETURNS TABLE (id INT, total NUMERIC) AS $$
BEGIN
  RETURN QUERY
    SELECT o.id, o.total
    FROM orders o WHERE o.user_id = uid;
END;
$$ LANGUAGE plpgsql;

Cas d'usage : Encapsuler de la logique métier complexe cote serveur pour réduire les allers-retours réseau.

Anti-pattern : Mettre toute la logique applicative en procédures stockées, rendant le debug et les tests très difficiles.
#sgbd#interview#database#postgresql

Subquery

PostgreSQL 🟡 Mid? entretien

Requête imbriquée dans une autre requête, utilisable dans SELECT, FROM, WHERE ou HAVING. Peut être corrélée (référence la requête externe) ou non-corrélée (indépendante).

Une question dans une question : 'Qui gagne plus que la moyenne des salaires ?'

SELECT name FROM employees
WHERE salary > (
  SELECT AVG(salary) FROM employees
);
-- Ou dans FROM
SELECT * FROM (
  SELECT name, COUNT(*) as cnt
  FROM orders GROUP BY name
) sub WHERE cnt > 5;

Cas d'usage : Filtrer sur un résultat agrégé ou créer des tables dérivées pour des requêtes complexes.

Anti-pattern : Utiliser des sous-requêtes corrélées dans le SELECT quand un JOIN serait plus performant.
#sgbd#interview#database#postgresql

Table

PostgreSQL 🟢 Junior

Structure de données relationnelle composée de lignes et colonnes avec un schema fixe. Chaque colonne a un type défini et chaque ligne représente un enregistrement.

Un tableau Excel avec des colonnes figées : impossible d'ajouter une cellule d'un type différent.

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(255) UNIQUE,
  created_at TIMESTAMP DEFAULT NOW()
);

Cas d'usage : Stocker des données structurées avec des relations fortes et des contraintes d'intégrité.

Anti-pattern : Créer une table avec des centaines de colonnes au lieu de normaliser en plusieurs tables.
#sgbd#interview#database#postgresql

Triggers

PostgreSQL 🟡 Mid? entretien

Fonctions exécutées automatiquement en réponse a un evenement (INSERT, UPDATE, DELETE) sur une table. Peuvent être BEFORE ou AFTER et opèrent par ligne (FOR EACH ROW) ou par instruction.

Un détecteur de mouvement qui déclenche automatiquement une alarme quand quelqu'un entre.

CREATE FUNCTION update_timestamp()
RETURNS trigger AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER set_timestamp
  BEFORE UPDATE ON users
  FOR EACH ROW EXECUTE FUNCTION update_timestamp();

Cas d'usage : Mettre a jour automatiquement un timestamp, maintenir un audit log ou propager des modifications.

Anti-pattern : Créer des cascades de triggers qui se déclenchent mutuellement, rendant le flux imprévisible.
#sgbd#interview#database#postgresql

uuidv7()

PostgreSQL 🟡 Mid? entretien

Fonction native ajoutée en PostgreSQL 18 (25 septembre 2025) qui génère des UUID version 7 : contrairement a UUIDv4 (aléatoire), les premiers bits d'un UUIDv7 encodent un timestamp, ce qui les rend triables chronologiquement et limite la fragmentation des index B-tree observée avec UUIDv4.

Comme numéroter des tickets dans l'ordre d'arrivée (uuidv7) plutôt que de tirer un numéro au hasard dans un sac (uuidv4) : le tri redevient naturel.

CREATE TABLE events (
  id uuid PRIMARY KEY DEFAULT uuidv7(),
  payload jsonb
);
-- Les id inseres restent ordonnes
-- chronologiquement dans l'index

Cas d'usage : Remplacer un UUIDv4 comme clé primaire quand l'ordre d'insertion doit rester exploitable, sans revenir a un SERIAL prévisible.

Anti-pattern : Garder uuidv4() par défaut sur une table a très fort volume d'écriture alors que la fragmentation d'index dégrade les performances.
#sgbd#interview#database#postgresql#pg18

VACUUM / ANALYZE

PostgreSQL 🔴 Senior

VACUUM récupéré l'espace des lignes mortes (MVCC). ANALYZE met a jour les statistiques du planificateur de requêtes. VACUUM ANALYZE fait les deux. Autovacuum les exécute automatiquement. PostgreSQL 17 (26 septembre 2024) réduit significativement la consommation mémoire de VACUUM grâce a un nouveau système de gestion mémoire dédiée.

VACUUM = le ramasse-miettes qui recycle les pages usées. ANALYZE = le recensement qui met a jour les cartes du quartier.

VACUUM ANALYZE users;
-- Verifier autovacuum
SELECT relname, last_vacuum, last_analyze
FROM pg_stat_user_tables;

Cas d'usage : Maintenir les performances de la base en récupérant l'espace et en mettant a jour les statistiques.

Anti-pattern : Désactiver autovacuum pour 'gagner en perf', causant un bloat progressif de la table.
#sgbd#interview#database#postgresql

Views / Materialized Views

PostgreSQL 🟡 Mid? entretien

Une View est une requête nommée (virtuelle, recalculee a chaque appel). Une Materialized View stocke physiquement le résultat et doit être rafraîchie manuellement.

View = regarder par la fenêtre en temps réel. Materialized View = une photo de la vue, rapide a consulter mais a actualiser.

CREATE MATERIALIZED VIEW monthly_sales AS
  SELECT date_trunc('month', created_at) as m,
    SUM(total) as revenue
  FROM orders GROUP BY m;
REFRESH MATERIALIZED VIEW CONCURRENTLY
  monthly_sales;

Cas d'usage : Materialized views pour des dashboards lourds a calculer, Views pour simplifier des requêtes complexes.

Anti-pattern : Oublier de rafraîchir la materialized view, affichant des données obsolètes.
#sgbd#interview#database#postgresql

WAL (Write-Ahead Log)

PostgreSQL 🔴 Senior

Journal de pre-écriture ou chaque modification est enregistrée avant d'être appliquée aux fichiers de données. Garantit la durabilite et permet la réplication et le point-in-time recovery.

Le brouillon du comptable : chaque opération est notée dans le journal avant d'être reportée dans le grand livre.

-- Verifier la taille du WAL
SELECT pg_size_pretty(
  pg_wal_lsn_diff(
    pg_current_wal_lsn(),
    '0/0'
  )
);

Cas d'usage : Comprendre la durabilite des données, configurer la réplication streaming ou le PITR.

#sgbd#interview#database#postgresql

Window Functions

PostgreSQL 🔴 Senior

Fonctions qui opèrent sur un ensemble de lignes (fenêtre) lie a la ligne courante sans réduire le nombre de résultats. Incluent ROW_NUMBER, RANK, LAG, LEAD, SUM OVER, etc.

Un coureur qui voit son classement en temps réel pendant la course, sans que la course s'arrête.

SELECT name, salary,
  RANK() OVER (ORDER BY salary DESC) as rank,
  salary - LAG(salary) OVER (ORDER BY salary DESC)
    as diff_with_prev
FROM employees;

Cas d'usage : Calculer des classements, des moyennes mobiles ou comparer chaque ligne avec la précédenté/suivante.

Anti-pattern : Utiliser des sous-requêtes corrélées pour simuler des window functions, beaucoup plus lent.
#sgbd#interview#database#postgresql