Leçon 11 / 20

Réduire les lignes traitées dans une requête

30 min SQL — modélisation, index et optimisation Gratuit

Objectif : Réorganiser une requête de retards pour limiter les lignes examinées tout en conservant ses résultats.

Une recherche de retards peut ralentir si elle transporte des emprunts qui ne sont pas en retard, ou si elle lit toutes les colonnes alors que le résultat n’en utilise que quelques-unes. Le coût augmente encore lorsque des jointures produisent des lignes intermédiaires qui ne servent pas à la réponse.

Vous allez partir d’une requête qui compte les emprunts encore en cours et dont la date de retour prévue est dépassée. Le modèle de la médiathèque fournit notamment les tables adherents et emprunts ; les colonnes utilisées ici sont adherent_id, emprunt_id, date_retour et date_retour_prevue.

Filtrer avant d’agréger

Un premier réflexe consiste à ne sélectionner que les emprunts qui répondent à la règle métier : ils ne sont pas rendus et leur échéance est antérieure à aujourd’hui. L’agrégation ne traite alors que ces lignes. Cette requête calcule, pour chaque adhérent concerné, le nombre d’emprunts en retard.

sql/requetes.sql — comptage des retards par adhérentSQL
-- Ne conserver que les emprunts encore en cours et échus.
SELECT
    e.adherent_id,
    COUNT(*) AS nombre_emprunts_en_retard
FROM emprunts AS e
WHERE e.date_retour IS NULL
  AND e.date_retour_prevue < CURRENT_DATE
GROUP BY e.adherent_id;
Résultat attendu
Une ligne par adhérent ayant au moins un emprunt en retard, avec son nombre d’emprunts concernés.

Le filtre est placé dans WHERE, avant le regroupement. L’agrégat reçoit ainsi seulement les emprunts qui satisfont les deux conditions. La projection est également limitée à l’identifiant regroupé et au résultat du comptage : les colonnes descriptives ne sont pas chargées sans nécessité.

Tester une présence avec EXISTS

Si la question porte sur les adhérents qui ont au moins un emprunt en retard, vous n’avez pas besoin de compter les emprunts ni de joindre toutes leurs lignes au résultat. EXISTS exprime directement ce test de présence. Sa sous-requête est corrélée à l’adhérent courant par adherent_id.

sql/requetes.sql — adhérents ayant au moins un retardSQL
-- Tester la présence d'un emprunt en retard pour chaque adhérent.
SELECT
    a.adherent_id
FROM adherents AS a
WHERE EXISTS (
    SELECT 1
    FROM emprunts AS e
    WHERE e.adherent_id = a.adherent_id
      AND e.date_retour IS NULL
      AND e.date_retour_prevue < CURRENT_DATE
);
Résultat attendu
Une ligne par adhérent ayant au moins un emprunt en retard.

Cette requête conserve une ligne par adhérent, même si plusieurs de ses emprunts sont en retard. Une jointure suivie d’un DISTINCT peut exprimer le même résultat, mais crée conceptuellement une ligne par correspondance avant de supprimer les doublons. Avec EXISTS, vous exprimez seulement la propriété recherchée : au moins une correspondance existe.

Vérifier le travail demandé au moteur

Exécutez EXPLAIN sur la requête de comptage, puis sur celle utilisant EXISTS. Regardez quelles tables sont lues, les accès estimés et les index retenus. Comme dans les leçons précédentes, interprétez rows comme une estimation et non comme un décompte garanti des lignes réellement traitées.

sql/diagnostics.sql — plans des deux formesSQL
-- Plan du comptage des emprunts en retard par adhérent.
EXPLAIN
SELECT
    e.adherent_id,
    COUNT(*) AS nombre_emprunts_en_retard
FROM emprunts AS e
WHERE e.date_retour IS NULL
  AND e.date_retour_prevue < CURRENT_DATE
GROUP BY e.adherent_id;

-- Plan du test de présence d'au moins un retard.
EXPLAIN
SELECT
    a.adherent_id
FROM adherents AS a
WHERE EXISTS (
    SELECT 1
    FROM emprunts AS e
    WHERE e.adherent_id = a.adherent_id
      AND e.date_retour IS NULL
      AND e.date_retour_prevue < CURRENT_DATE
);

Ne choisissez pas une forme uniquement parce qu’elle paraît plus courte. Vérifiez aussi que la requête répond bien à la même question : compter les retards par adhérent n’est pas équivalent à lister les adhérents qui en ont au moins un. Dans sql/diagnostics.sql, notez la requête testée, les données utilisées et les éléments du plan qui motivent votre conclusion.

À retenir

  • Filtrez les emprunts en retard avant de les agréger.
  • Sélectionnez seulement les colonnes nécessaires ; évitez SELECT * lorsque le résultat n’en a pas besoin.
  • Utilisez EXISTS pour exprimer un test de présence sans demander les lignes correspondantes dans le résultat.
  • Comparez les plans avec EXPLAIN et vérifiez que chaque requête répond bien à la même question métier.

Dans la prochaine leçon, vous comparerez des plans et validerez l’équivalence des réécritures sur des jeux de test.

Envie d'aller plus loin ?

Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement encadré, nos formations professionnelles sont animées par les mêmes formateurs.