14.1.8 Sous-sélections ( SubSELECT )
14.1 Manipulation de données : SELECT , INSERT , UPDATE , DELETE
14 Syntaxe des commandes SQL
Manuel de Référence MySQL 4.1 : Version Française
. Les sous-requêtes comme opérateur scalaire . Comparaisons avec les sous-requêtes . Sous-requêtes avec les clauses ANY , IN et SOME . Sous-requêtes avec ALL . Sous-requêtes corrélées . EXISTS et NOT EXISTS . Sous-requêtes de ligne . Sous-requêtes dans la clause FROM . Erreurs de sous-requêtes ->Optimisation des sous-requêtes . Se passer des sous-requêtes avec les premières versions de MySQL
|
14.1.8.10 Optimisation des sous-requêtes
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
.
|