Le développement des sous-requêtes se poursuit, et aucun des conseils d'optimisation ne sera valable longtemps. Voici quelques astuces que vous voulez prendre en compte :
Utiliser une clause de sous-requête pour affecter le nombre ou l'ordre des lignes dans une sous-requête, par exemple :
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
Remplacer une jointure par une sous-requête. Par exemple :
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN ( SELECT column1 FROM t2);
au lieu de
SELECT DISTINCT t1.column1 FROM t1, t2 WHERE t1.column1 = t2.column1;
Déplacer une clause FROM
externe dans
une sous-requête, comme ceci :
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
au lieu de
SELECT * FROM t1 WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
Un autre exemple :
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
au lieu de
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
Utiliser une sous-requête de ligne plutôt qu'une corrélation. Par exemple :
SELECT * FROM t1 WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
au lieu de
SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1 AND t2.column2=t1.column2);
Utiliser NOT (a = ANY (...))
au lieu de
a <> ALL (...)
.
Utiliser x = ANY (table containing
{1,2})
plutôt que x=1 OR
x=2
.
Utiliser = ANY
de préférence à
EXISTS
Le truc ci-dessus peut accélérer certains programmes, et en
ralentir d'autres. En utilisant la fonction utilitaire
BENCHMARK()
, vous pouvez obtenir une idée
de votre cas. Ne vous attardez pas trop à transformer vos
jointures, sauf si la compatibilité avec les anciennes
versions est importante pour vous.
Quelques optimisation que MySQL va prendre en charge lui-même :
MySQL va exécuter les sous-requêtes non corrélées une
seule fois (utilisez la commande
EXPLAIN
pour vous assurer que les
requêtes ne sont pas correllées).
MySQL va transformer les sous-requêtes
IN
/ALL
/ANY
/SOME
pour essayer de profiter de la possibilité que les
colonnes sélectionnées dans la sous-requêtes sont
indexées.
MySQL remplacera les sous-requêtes de la forme
... IN (SELECT indexed_column FROM single_table ...)
par une recherche dans un index, que
EXPLAIN
décrira comme une jointure de
type spécial.
MySQL va améliorer les expressions de la forme
valeur {ALL|ANY|SOME} {> | < | >= | <=} (sous-requête non-correllée)
avec une expression impliquant MIN
ou
MAX
(à moins d'une valeur
NULL
ou d'ensembles
SET
vides). Par exemple,
WHERE 5 > ALL (SELECT x FROM t)
revient à
WHERE 5 > (SELECT MAX(x) FROM t)
Il y a un chapitre intitulé ``Comment MySQL adapte les
sous-requêtes'' dans les manuels internes de MySQL, que vous
pouvez trouver en téléchargeant les sources de MySQL : il
est dans un fichier appelé
internals.texi
, dans le dossier
Docs
.
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.