IN vs EXISTS en Oracle : lequel est le plus rapide ?

IN vs EXISTS en SQL Oracle : fonctionnement, performance, le piège de NOT IN avec les NULL et quand préférer NOT EXISTS, avec des exemples.

Comparatif IN vs EXISTS en Oracle

IN et EXISTS servent tous deux à tester l’appartenance dans une sous-requête, mais EXISTS s’arrête dès la première correspondance trouvée, tandis que IN évalue toute la liste. Lequel est le plus rapide ? Ça dépend des données — voici la règle pratique et les exemples Oracle.

Publicité

Syntaxe : deux façons d’écrire la même intention

-- clients ayant au moins une commande

-- avec IN
SELECT * FROM clients c
WHERE c.id IN (SELECT client_id FROM commandes);

-- avec EXISTS
SELECT * FROM clients c
WHERE EXISTS (SELECT 1 FROM commandes cmd WHERE cmd.client_id = c.id);

La différence de fonctionnement

  • IN : construit l’ensemble des valeurs de la sous-requête, puis vérifie l’appartenance.
  • EXISTS : pour chaque ligne externe, teste s’il existe au moins une ligne correspondante, et s’arrête au premier match (corrélé).

Quel est le plus rapide ?

Avec les optimiseurs Oracle modernes, les deux donnent souvent le même plan d’exécution. La règle empirique reste utile :

  • EXISTS est avantageux quand la sous-requête est grande et qu’on cherche juste « existe-t-il… ? » (il s’arrête tôt).
  • IN est pratique quand la sous-requête renvoie une petite liste de valeurs.

Dans le doute, comparez avec EXPLAIN PLAN — c’est le seul juge fiable.

Le piège majeur : NOT IN et les NULL

C’est LA raison de préférer souvent NOT EXISTS : si la sous-requête de NOT IN contient une seule valeur NULL, le résultat devient… vide (aucune ligne) !

-- ❌ DANGER : si commandes.client_id contient un NULL, 0 ligne renvoyée
SELECT * FROM clients
WHERE id NOT IN (SELECT client_id FROM commandes);

-- ✅ robuste face aux NULL
SELECT * FROM clients c
WHERE NOT EXISTS (SELECT 1 FROM commandes cmd WHERE cmd.client_id = c.id);

Pour les clients sans commande, préférez donc NOT EXISTS (ou un LEFT JOIN … IS NULL).

Et la jointure dans tout ça ?

Souvent, un simple JOIN exprime la même chose plus clairement et aussi efficacement :

SELECT DISTINCT c.*
FROM clients c JOIN commandes cmd ON cmd.client_id = c.id;

(Attention au DISTINCT qui peut coûter cher : EXISTS l’évite naturellement.)

Récapitulatif

  • « Au moins une correspondance » sur grosse sous-requête → EXISTS.
  • Petite liste de valeurs fixes → IN.
  • « Ceux qui n’ont pas… » → NOT EXISTS (jamais NOT IN avec des NULL possibles).

FAQ

IN ou EXISTS : la performance change-t-elle vraiment ?

Sur Oracle récent, souvent non (même plan). La différence se voit surtout sur de très gros volumes ou des sous-requêtes corrélées — mesurez avec EXPLAIN PLAN.

Pourquoi NOT IN renvoie 0 ligne parfois ?

Parce que la sous-requête contient une valeur NULL : en logique SQL, « x NOT IN (…, NULL) » devient indéterminé. Utilisez NOT EXISTS.

EXISTS avec SELECT 1 ou SELECT * ?

Aucune différence de performance : Oracle ne lit pas les colonnes dans un EXISTS. SELECT 1 est juste une convention de lisibilité.

Un nouveau tutoriel SQL par semaine

Nous ne spammons pas ! Consultez notre politique de confidentialité pour plus d’informations.

Publicité

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Cours SQL & Oracle — 100% gratuitVoir les cours →