0Pricing
SQL Academy · Leçon

Performances de EXISTS et JOIN

Choisissez le modèle le plus rapide.

Performances de EXISTS et JOIN est une leçon SQL Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage SQL Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours SQL Academy comprend 4 leçons au total.

Pourquoi les performances comptent ici

Lorsque vous devez vérifier si des lignes associées existent dans une autre table, SQL vous offre plusieurs outils : EXISTS, IN et JOIN. Chacun produit des résultats corrects, mais leurs performances peuvent être très différentes selon la taille de vos données, vos index et le moteur de base de données.

Dans cette leçon, vous apprendrez comment chaque approche fonctionne en interne et dans quels cas choisir l'une ou l'autre.

Tables d'exemple

Nous utiliserons deux tables tout au long de cette leçon : customers et orders. Un client peut avoir zéro ou plusieurs commandes. Il s'agit d'une relation classique un-à-plusieurs, idéale pour évaluer les modèles EXISTS et JOIN.

CREATE TABLE customers (
  id   SERIAL PRIMARY KEY,
  name VARCHAR(100)
);

CREATE TABLE orders (
  id          SERIAL PRIMARY KEY,
  customer_id INT REFERENCES customers(id),
  total       NUMERIC(10,2)
);

INSERT INTO customers (name) VALUES
  ('Alice'), ('Bob'), ('Carol'), ('Dave');

INSERT INTO orders (customer_id, total) VALUES
  (1, 120.00), (1, 85.50), (3, 200.00);

L'approche JOIN

Une méthode courante consiste à utiliser INNER JOIN pour trouver les clients qui ont au moins une commande. Cela fonctionne, mais remarquez le problème : si un client a cinq commandes, il apparaît cinq fois dans l'ensemble de résultats avant que DISTINCT ne les regroupe en une seule occurrence.

Cette duplication représente un travail supplémentaire pour la base de données : elle construit d'abord le résultat complet de la jointure, puis supprime les doublons.

SELECT DISTINCT c.id, c.name
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id;

L'approche EXISTS

EXISTS répond à une question oui/non : existe-t-il au moins une ligne correspondante ? Dès que le moteur trouve la première correspondance, il arrête le parcours — on appelle cela une évaluation par court-circuit.

Aucun doublon n'est produit et DISTINCT n'est pas nécessaire, car EXISTS ne renvoie jamais réellement les lignes internes.

SELECT c.id, c.name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

Le court-circuit est essentiel

L'évaluation par court-circuit signifie que la sous-requête s'arrête dès qu'une ligne satisfaisant les critères est trouvée. Qu'un client ait 1 commande ou 10 000 commandes, EXISTS ne lit que jusqu'à la première correspondance.

Un JOIN doit lire toutes les lignes correspondantes pour construire l'ensemble de résultats, même lorsque seule l'existence vous importe. Dans les tables larges comportant de nombreuses lignes enfants par ligne parente, cette différence s'amplifie rapidement.

-- EXISTS stops after finding row #1
SELECT c.name
FROM customers c
WHERE EXISTS (
  SELECT 1          -- 'SELECT 1' is conventional; the value does not matter
  FROM orders o
  WHERE o.customer_id = c.id
);

-- JOIN scans ALL matching order rows
SELECT DISTINCT c.name
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id;

NOT EXISTS et LEFT JOIN ... IS NULL

Pour le contrôle inverse — trouver les clients qui n'ont aucune commande — vous pouvez utiliser NOT EXISTS ou le modèle LEFT JOIN ... WHERE IS NULL. Les deux sont courants, mais NOT EXISTS est généralement plus lisible et l'optimiseur le préfère souvent.

-- NOT EXISTS
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
);

-- LEFT JOIN ... IS NULL (equivalent result)
SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

Le rôle des index

EXISTS et JOIN tirent tous deux énormément profit d'un index sur la colonne de clé étrangère. Sans index sur orders.customer_id, chaque ligne externe déclenche un parcours complet de la table orders.

Ajouter cet index constitue souvent le gain de performances le plus important — plus déterminant que le choix entre EXISTS et JOIN.

-- Create an index on the foreign key
CREATE INDEX idx_orders_customer_id ON orders(customer_id);

-- Now both patterns use an index lookup instead of a full scan
EXPLAIN
SELECT c.name
FROM customers c
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.id
);

Lire la sortie de EXPLAIN

Utilisez EXPLAIN (ou EXPLAIN ANALYZE pour également exécuter la requête) afin de voir comment la base de données exécute une requête. Voici les indices à rechercher :

  • Parcours d'index — bien ; l'index est utilisé.
  • Parcours séquentiel sur une grande table — potentiellement un signal d'alerte ; un index pourrait aider.
  • Jointure par hachage / boucle imbriquée — algorithme de jointure choisi ; les boucles imbriquées s'accordent bien avec les parcours d'index.
EXPLAIN ANALYZE
SELECT c.name
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name
HAVING COUNT(o.id) > 0;

Quand JOIN est préférable

EXISTS excelle pour les vérifications d'existence pure. Mais si vous avez également besoin de données provenant de la table associée — comme le montant ou la date de la commande — vous devez utiliser un JOIN. Il n'existe aucun moyen de renvoyer des colonnes depuis une sous-requête EXISTS.

Choisissez l'outil adapté à la question : EXISTS pour « est-ce que cela existe ? », JOIN pour « donnez-moi les données des deux tables ».

-- Need order data? JOIN is the only option.
SELECT c.name, o.total, o.id AS order_id
FROM customers c
INNER JOIN orders o ON o.customer_id = c.id
ORDER BY c.name;

IN ou EXISTS sur de grands ensembles

IN (subquery) évalue d'abord l'intégralité de la sous-requête, construit une liste de valeurs en mémoire, puis compare chaque ligne externe à cette liste. Avec des millions de lignes, cette liste peut épuiser la mémoire.

EXISTS est évalué ligne par ligne et interrompt son évaluation dès qu'une correspondance est trouvée ; il ne matérialise donc jamais l'ensemble complet des résultats internes. Pour les vérifications corrélées sur de grands ensembles, EXISTS est presque toujours plus rapide que IN.

-- IN builds the full list first
SELECT name
FROM customers
WHERE id IN (
  SELECT customer_id FROM orders
);

-- EXISTS evaluates per-row and short-circuits
SELECT name
FROM customers c
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.customer_id = c.id
);

Aide-mémoire décisionnel

Voici une référence rapide pour choisir le modèle adapté :

  • EXISTS — vous devez seulement savoir si une correspondance existe ; grandes tables enfants ; NOT EXISTS pour une anti-jointure.
  • JOIN — vous avez besoin de colonnes de la table associée ; agrégations sur les deux tables.
  • IN — listes courtes de valeurs statiques (WHERE status IN ('active', 'pending')) ; à éviter pour les grandes sous-requêtes.
  • Indexez toujours la colonne de clé étrangère — cela compte davantage que le choix de la syntaxe.

Vérification rapide

Quelle proposition explique le mieux pourquoi EXISTS peut être plus rapide que INNER JOIN + DISTINCT lorsqu'il s'agit de vérifier la présence de lignes associées ?

Récapitulatif de la leçon

Dans cette leçon, vous avez appris à choisir entre EXISTS et JOIN pour optimiser les performances en SQL :

  • EXISTS s'arrête dès la première correspondance — il cesse le parcours dès qu'une correspondance est trouvée, ce qui évite les doublons sans nécessiter DISTINCT.
  • JOIN renvoie toutes les lignes correspondantes — utilisez-le lorsque vous avez besoin de données de la table associée, mais ajoutez DISTINCT ou GROUP BY si vous ne vous intéressez qu'à la ligne parente.
  • NOT EXISTS est un modèle d'anti-jointure propre ; LEFT JOIN ... IS NULL est équivalent, mais plus verbeux.
  • Évitez IN avec les grandes sous-requêtes — il matérialise l'intégralité du résultat interne ; EXISTS utilise la mémoire plus efficacement.
  • Indexez vos clés étrangères — cette seule étape apporte souvent le gain de performance le plus important, quelle que soit la syntaxe choisie.
  • Utilisez EXPLAIN / EXPLAIN ANALYZE pour vérifier le plan d'exécution et confirmer que les index sont utilisés.

Questions Fréquemment Posées

La leçon « Performances de EXISTS et JOIN » est-elle gratuite ?

Oui — le texte complet de « Performances de EXISTS et JOIN » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours SQL Academy, passe à CoddyKit PRO. Le cours SQL Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Performances de EXISTS et JOIN » ?

Choisissez le modèle le plus rapide. Tu pratiques SQL Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer SQL Academy ?

Aucune expérience préalable n'est requise. SQL Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Performances de EXISTS et JOIN » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon SQL Academy ?

Oui. Chaque leçon SQL Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Sous-requêtes corrélées
  2. EXISTS et NOT EXISTS
  3. IN, ANY ou ALL
  4. Performances de EXISTS et JOIN
← Retour à SQL Academy