Retour au blog
6 min de lecture

5 techniques SQL pour optimiser vos requêtes et réduire les temps de traitement

Une requête qui tourne 45 secondes peut souvent être ramenée à 2 secondes avec les bons réflexes. Voici cinq techniques que j'applique systématiquement sur mes projets pour écrire du SQL performant sur de grands volumes.

Optimisation SQL

Pourquoi l'optimisation SQL est un vrai sujet en 2026

Les volumes de données ont explosé. Ce qui fonctionnait bien sur 500 000 lignes devient douloureux sur 50 millions. Et pourtant, la plupart des problèmes de performance SQL viennent de mauvaises habitudes d'écriture plutôt que de limites matérielles. Avant d'augmenter la puissance de votre serveur, vérifiez que vos requêtes sont bien écrites.

Technique 1 : utiliser les index intelligemment

Un index bien placé est la première chose à regarder quand une requête rame. Le principe est simple : la base de données maintient une structure triée sur les colonnes indexées, ce qui évite de scanner toute la table à chaque requête.

Trois règles à retenir :

  • Indexez les colonnes utilisées dans les clauses WHERE, JOIN et ORDER BY
  • N'indexez pas tout : chaque index ralentit les opérations d'écriture (INSERT, UPDATE, DELETE)
  • Préférez les index composites quand vous filtrez toujours sur plusieurs colonnes ensemble

Pour vérifier si vos index sont utilisés, consultez le plan d'exécution de votre requête (EXPLAIN sur PostgreSQL/MySQL, bouton "Inclure le plan d'exécution" sur SQL Server).

-- Index simple sur une colonne fréquemment filtrée
CREATE INDEX idx_commandes_date ON commandes(date_commande);

-- Index composite quand on filtre toujours sur client + statut
CREATE INDEX idx_commandes_client_statut
ON commandes(client_id, statut);

Technique 2 : les CTE plutôt que les sous-requêtes imbriquées

Les Common Table Expressions (CTE) avec la syntaxe WITH rendent vos requêtes lisibles et évitent les sous-requêtes imbriquées qui deviennent rapidement illisibles et difficiles à debugger.

Au-delà de la lisibilité, les CTE permettent aussi de décomposer une requête complexe en étapes logiques, ce qui facilite l'identification des parties lentes.

-- Moins lisible : sous-requête imbriquée
SELECT client_id, total
FROM (
    SELECT client_id, SUM(montant) as total
    FROM commandes
    WHERE statut = 'validée'
    GROUP BY client_id
) AS commandes_valides
WHERE total > 1000;

-- Plus lisible et maintenable : CTE
WITH commandes_valides AS (
    SELECT client_id, SUM(montant) as total
    FROM commandes
    WHERE statut = 'validée'
    GROUP BY client_id
)
SELECT client_id, total
FROM commandes_valides
WHERE total > 1000;
Attention

Sur certains moteurs SQL (notamment MySQL avant la version 8), les CTE ne sont pas matérialisées et peuvent être moins performantes que des sous-requêtes dans certains cas. Testez toujours avec vos volumes réels.

Technique 3 : les fonctions de fenêtrage pour remplacer les auto-jointures

Les fonctions de fenêtrage (OVER) sont l'une des fonctionnalités SQL les plus sous-utilisées. Elles permettent de faire des calculs sur un ensemble de lignes en relation avec la ligne courante, sans avoir à joindre la table sur elle-même.

Exemple concret : calculer le rang des vendeurs par région sans auto-jointure.

-- Avec auto-jointure (lent sur les gros volumes)
SELECT v1.vendeur, v1.region, v1.ca,
       COUNT(v2.vendeur) + 1 AS rang
FROM ventes v1
LEFT JOIN ventes v2
  ON v1.region = v2.region AND v2.ca > v1.ca
GROUP BY v1.vendeur, v1.region, v1.ca;

-- Avec fonction de fenêtrage (beaucoup plus rapide)
SELECT vendeur, region, ca,
       RANK() OVER (PARTITION BY region ORDER BY ca DESC) AS rang
FROM ventes;

Les fonctions utiles à maîtriser : RANK(), ROW_NUMBER(), LAG(), LEAD(), SUM() OVER, AVG() OVER.

Technique 4 : éviter SELECT * en production

C'est un réflexe à prendre dès le départ. SELECT * est commode pour explorer les données, mais en production il est problématique pour plusieurs raisons :

  • Il transfère toutes les colonnes même celles dont vous n'avez pas besoin, ce qui surcharge le réseau et la mémoire
  • Il empêche l'utilisation d'index couvrants (covering indexes) qui évitent d'accéder aux données de la table
  • Si la structure de la table change (ajout ou suppression de colonne), votre requête se comporte différemment sans erreur visible

Listez toujours explicitement les colonnes dont vous avez besoin, même si c'est plus verbeux.

Technique 5 : lire et comprendre le plan d'exécution

Le plan d'exécution est la radiographie de votre requête. Il vous montre comment le moteur SQL a décidé d'exécuter votre code : quels index il utilise, dans quel ordre il joint les tables, où il fait des scans complets.

Les signaux d'alarme à repérer dans un plan d'exécution :

  • Full Table Scan (Seq Scan) sur une grande table : la base scanne toute la table, un index manque probablement
  • Hash Join ou Nested Loop sur de gros volumes : la jointure est coûteuse, vérifiez que les colonnes de jointure sont indexées
  • Coût estimé très élevé : sur SQL Server, un coût de sous-arbre supérieur à quelques milliers mérite investigation
-- Sur PostgreSQL : afficher le plan d'exécution
EXPLAIN ANALYZE
SELECT c.client_id, c.nom, SUM(o.montant)
FROM clients c
JOIN commandes o ON c.client_id = o.client_id
WHERE o.date_commande >= '2025-01-01'
GROUP BY c.client_id, c.nom;

En résumé

Ces cinq techniques couvrent la grande majorité des problèmes de performance SQL que l'on rencontre sur le terrain. L'ordre d'application logique est : d'abord vérifier les index, ensuite réécrire les requêtes avec des CTE et des fonctions de fenêtrage, puis éliminer les SELECT *, et enfin utiliser le plan d'exécution pour confirmer que les optimisations ont bien l'effet attendu.

L'optimisation SQL est une compétence qui se développe avec la pratique. Le meilleur investissement reste de lire les plans d'exécution régulièrement, même sur des requêtes qui semblent rapides.