Les bases de données SQL utilisent deux algorithmes entièrement
différents pour le group by
. Le premier, un algorithme
de hachage, agrège les enregistrements en entrée dans une table de
hachage temporaire. Une fois tous les enregistrements en entrée traitées,
la table de hachage est renvoyée comme résultat. Le deuxième algorithme,
l'algorithme de tri/groupe, trie en premier lieu les données en entrée en
suivant la clé de groupement pour que les lignes de chaque groupe se
suivent les unes les autres en une succession immédiate. Après cela, la
base de données a juste besoin de les regrouper. En général, les deux
algorithmes ont besoin de matérialiser un état intermédiaire, donc elles
ne sont pas exécutées via un pipeline. Néanmoins, l'algorithme de
tri/groupe peut utiliser un index pour éviter l'opération de tri, et du
coup activer l'exécution du group by
en
pipeline.
Remarque
MySQL 5.7 n'utilise pas l'algorithme de hachage. Néanmoins, l'optimisation pour l'algorithme tri/groupe fonctionne comme décrit ci-dessus.
Considérez la requête suivante. Elle renvoie les revenus d'hier
groupés par ID_PRODUIT
:
SELECT id_produit, sum(valeur_eur)
FROM ventes
WHERE date_vente = TRUNC(sysdate) - INTERVAL '1' DAY
GROUP BY id_produit;
En connaissant l'index sur DATE_VENTE
et
ID_PRODUIT
de la section
précédente, l'algorithme de tri/groupe est plus approprié car un
INDEX RANGE SCAN
renvoie
automatiquement les lignes dans l'ordre requis. Ceci signifie que la base
de données évite la matérialisation car elle n'a pas besoin d'une
opération explicite de tri. Le group by
est exécuté en
pipeline.
------------------------------------------------------------------
|Id |Operation | Name | Rows | Cost |
------------------------------------------------------------------
| 0 |SELECT STATEMENT | | 17 | 192 |
| 1 | SORT GROUP BY NOSORT | | 17 | 192 |
| 2 | TABLE ACCESS BY INDEX ROWID| VENTES | 321 | 192 |
|*3 | INDEX RANGE SCAN | DATE_VENTES_PR | 321 | 3 |
------------------------------------------------------------------
Le plan d'exécution de la base de données Oracle marque une
opération SORT GROUP BY
en pipeline avec le mot-clé
NOSORT
. Le plan d'exécution des autres bases de données ne
mentionne pas du tout les opérations de tri.
Le group by
en pipeline a les mêmes prérequis que
le order by
en pipeline, sauf qu'il n'y a aucun
modificateur ASC
et DESC
. Cela signifie que
définir un index avec les modificateurs ASC
/DESC
ne devrait pas affecter l'exécution en pipeline d'un group
by
. C'est aussi vrai pour NULLS
FIRST
/LAST
. Cependant, certaines bases de données ne
peuvent pas utiliser correctement un index
ASC
/DESC
pour un group by
exécuté en pipeline.
Attention
PostgreSQL ne réalise pas automatiquement un group
by
en pipeline si l'index traite la valeur NULL
comme la plus petite valeur possible. Ajouter une clause
order by
du même ordre que l'index contourne ce
problème.
Pour PostgreSQL, vous devez ajouter une clause order
by
pour qu'un index avec un tri NULLS LAST
puisse être utilisé avec un group by
dans un
pipeline.
La base de données Oracle ne peut pas lire un index à l'envers
pour exécuter un group by
dans un pipeline s'il est
suivi par un order by
.
Plus de détails sont disponibles dans les annexes respectives : PostgreSQL, Oracle.
Si nous étendons la requête pour qu'elle considère toutes les ventes
depuis hier, comme nous l'avions fait dans l'exemple
sur l'order by
en pipeline, cela empêche le
group by
en pipeline pour la même raison que
précédemment : le INDEX RANGE SCAN
ne fournit pas les lignes
triées par la clé de regroupement (comparez à la Figure 6.1).
SELECT id_produit, sum(valeur_eur)
FROM ventes
WHERE date_vente >= TRUNC(sysdate) - INTERVAL '1' DAY
GROUP BY id_produit;
À la place, la base de données Oracle utilise l'algorithme de hachage. L'avantage de cet algorithme est qu'il est seulement nécessaire de mettre en cache le résultat agrégé alors que l'algorithme de tri/groupe matérialise l'ensemble complet en entrée. En d'autres termes, l'algorithme de hachage a besoin de moins de mémoire.
Comme avec un order by
exécuté en pipeline, une
exécution rapide n'est pas l'aspect le plus important d'une exécution
group by
en pipeline. Il est plus important que la base
de données l'exécute via un pipeline et renvoie les premiers résultats
avant de lire l'entrée en entier. C'est la condition pour les méthodes
d'optimisation avancées expliquées dans le prochain chapitre.
Réflexion
Pouvez-vous trouver d'autres opérations des bases de données (en dehors du tri et des groupes) pouvant utiliser un index pour éviter un tri ?