Ordre des opérations SQL – Dans quel ordre MySQL exécute les requêtes ?

Optimisez votre base de données, de façon auto-magique.
Cliquez pour commencer, gratuitement.

Savoir les bits et les octets de l’ordre des opérations d’une requête SQL peut être très précieux, car cela peut faciliter le processus d’écriture de nouvelles requêtes, tout en étant également très bénéfique lorsqu’on essaie d’optimiser une requête SQL.

Si vous cherchez la version courte, il s’agit de l’ordre logique des opérations, également connu comme l’ordre d’exécution, pour une requête SQL :

  1. DE, y compris les JOIN
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. Fonctions WINDOW
  6. SELECT
  7. DISTINCT
  8. UNION
  9. ORDER PAR
  10. LIMITE et OFFSET

Mais la réalité n’est pas aussi simple ni aussi directe. Comme nous l’avons dit, la norme SQL définit l’ordre d’exécution des différentes clauses des requêtes SQL. Cela dit, les bases de données modernes remettent déjà en question cet ordre par défaut en appliquant certaines astuces d’optimisation qui pourraient changer l’ordre réel d’exécution, bien qu’elles doivent finir par retourner le même résultat que si elles exécutaient la requête selon l’ordre d’exécution par défaut.

Pourquoi feraient-elles cela ? Eh bien, il peut être idiot que la base de données aille d’abord chercher toutes les données mentionnées dans la clause FROM (y compris les JOIN), avant de se pencher sur la clause WHERE et ses index. Ces tables peuvent contenir beaucoup de données, donc vous pouvez imaginer ce qui se passera si l’optimiseur de la base de données s’en tient à l’ordre traditionnel des opérations d’une requête SQL.

Regardons chacune des parties de la requête SQL selon leur ordre d’exécution.

FROM et JOINs

Les tables spécifiées dans la clause FROM (y compris les JOINs), seront évaluées en premier, pour déterminer l’ensemble de travail qui est pertinent pour la requête. La base de données fusionnera les données de toutes les tables, selon les clauses JOINs ON, tout en récupérant également les données des sous-requêtes, et pourrait même créer certaines tables temporaires pour contenir les données retournées par les sous-requêtes de cette clause.

Dans de nombreux cas cependant, l’optimiseur de la base de données choisira d’évaluer la partie WHERE en premier, pour voir quelle partie de l’ensemble de travail peut être laissée de côté (de préférence en utilisant des index), afin de ne pas trop gonfler l’ensemble de données s’il n’est pas vraiment nécessaire.

Clause WHERE

La clause WHERE sera la deuxième à être évaluée, après la clause FROM. Nous avons l’ensemble de données de travail en place, et maintenant nous pouvons filtrer les données selon les conditions de la clause WHERE.

Ces conditions peuvent inclure des références aux données et aux tables de la clause FROM, mais ne peuvent pas inclure de références aux alias définis dans la clause SELECT, car ces données et ces alias peuvent ne pas encore ‘exister’ dans ce contexte, car cette clause n’a pas encore été évaluée par la base de données.

Aussi, un piège commun pour la clause WHERE serait d’essayer de filtrer les valeurs agrégées dans la clause WHERE, par exemple avec cette clause : « WHERE sum(available_stock) > 0 ». Cette déclaration fera échouer l’exécution de la requête, car les agrégations seront évaluées plus tard dans le processus (voir la section GROUP BY ci-dessous). Pour appliquer une condition de filtrage sur des données agrégées, vous devez utiliser la clause HAVING et non la clause WHERE.

Clause GROUP BY

Maintenant que nous avons filtré l’ensemble des données à l’aide de la clause WHERE, nous pouvons agréger les données selon une ou plusieurs colonnes apparaissant dans la clause GROUP BY. Le regroupement des données consiste en fait à les diviser en différents morceaux ou seaux, où chaque seau possède une clé et une liste de lignes qui correspondent à cette clé. Ne pas avoir de clause GROUP BY revient à mettre toutes les lignes dans un seul énorme seau.

Une fois que vous avez agrégé les données, vous pouvez maintenant utiliser des fonctions d’agrégation pour retourner une valeur par groupe pour chacun des seaux. De telles fonctions d’agrégation comprennent COUNT, MIN, MAX, SUM et autres.

Clause HAVING

Maintenant que nous avons regroupé les données à l’aide de la clause GROUP BY, nous pouvons utiliser la clause HAVING pour filtrer certains seaux. Les conditions de la clause HAVING peuvent faire référence aux fonctions d’agrégation, ainsi l’exemple qui ne fonctionnait pas dans la clause WHERE ci-dessus, fonctionnera très bien dans la clause HAVING : « HAVING sum(available_stock) > 0 ».

Comme nous avons déjà regroupé les données, nous ne pouvons plus accéder aux lignes d’origine à ce stade, donc nous ne pouvons appliquer des conditions pour filtrer des seaux entiers, et non des lignes individuelles dans un seau.

Aussi, comme nous l’avons mentionné dans les sections précédentes, les alias définis dans la clause SELECT ne peuvent pas non plus être accédés dans la section, car ils n’ont pas encore été évalués par la base de données (ceci est vrai dans la plupart des bases de données).

Fonctions Window

Si vous utilisez des fonctions Window, c’est le point où elles seront exécutées. Tout comme le mécanisme de regroupement, les fonctions Window effectuent également un calcul sur un ensemble de lignes. La principale différence est que lors de l’utilisation des fonctions Window, chaque ligne conservera sa propre identité et ne sera pas regroupée dans un seau d’autres lignes similaires.

Les fonctions Window ne peuvent être utilisées que dans la clause SELECT ou ORDER BY. Vous pouvez utiliser des fonctions d’agrégation à l’intérieur des fonctions Window, par exemple :

SUM(COUNT(*)) OVER ()

Clause SELECT

Maintenant que nous avons fini d’écarter les lignes de l’ensemble de données et de regrouper les données, nous pouvons sélectionner les données que nous voulons extraire de la requête vers le côté client. Vous pouvez utiliser des noms de colonnes, des agrégations et des sous-requêtes dans la clause SELECT. Gardez à l’esprit que si vous utilisez une référence à une fonction d’agrégation, comme COUNT(*) dans la clause SELECT, il s’agit simplement d’une référence à une agrégation qui s’est déjà produite lorsque le regroupement a eu lieu, donc l’agrégation elle-même ne se produit pas dans la clause SELECT, mais c’est seulement une référence à son ensemble de résultats.

Mot clé DISTINCT

La syntaxe du mot clé DISTINCT est un peu déroutante, parce que le mot clé prend sa place avant les noms de colonnes dans la clause SELECT. Mais, l’opération DISTINCT réelle a lieu après le SELECT. Lors de l’utilisation du mot clé DISTINCT, la base de données écartera les lignes avec des valeurs en double des lignes restantes après que le filtrage et les agrégations aient eu lieu.

Mot clé UNION

Le mot clé UNION combine les ensembles de résultats de deux requêtes en un seul ensemble de résultats. La plupart des bases de données vous permettront de choisir entre UNION DISTINCT (qui écartera les lignes en double de l’ensemble de résultats combiné) ou UNION ALL (qui combine simplement les ensembles de résultats sans appliquer de contrôle de duplication).

Vous pouvez appliquer le tri (ORDER BY) et la limitation (LIMIT) sur l’ensemble de résultats de l’UNION, de la même manière que vous pouvez l’appliquer sur une requête ordinaire.

Clause ORDER BY

Le tri a lieu une fois que la base de données a l’ensemble des résultats prêts (après le filtrage, le regroupement, la suppression des doublons). Une fois que nous avons cela, la base de données peut maintenant trier le jeu de résultats en utilisant des colonnes, des alias sélectionnés ou des fonctions d’agrégation, même s’ils ne font pas partie des données sélectionnées. La seule exception est l’utilisation du mot-clé DISTINCT, qui empêche le tri par une colonne non sélectionnée, car dans ce cas, l’ordre du jeu de résultats sera indéfini.

Vous pouvez choisir de trier les données en utilisant un ordre décroissant (DESC) ou un ordre croissant (ASC). L’ordre peut être unique pour chacune des parties de l’ordre, donc ce qui suit est valide : ORDER BY firstname ASC, age DESC

LIMIT et OFFSET

Dans la plupart des cas d’utilisation (à l’exception de quelques-uns comme le reporting), nous voudrions écarter toutes les lignes sauf les X premières lignes du résultat de la requête. La clause LIMIT, qui est exécutée après le tri, nous permet de faire exactement cela. En outre, vous pouvez choisir à partir de quelle ligne vous voulez commencer à extraire les données et combien vous voulez en exclure, en utilisant une combinaison des mots-clés LIMIT et OFFSET. L’exemple suivant récupérera 50 lignes à partir de la ligne n°100 : LIMIT 50 OFFSET 100

Optimisez votre base de données, de façon auto-magique.
Cliquez pour commencer, gratuitement.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.