| 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 : 
 
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.
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 : 
au lieu de| 
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2);
 | 
 | 
SELECT DISTINCT t1.column1 FROM t1, t2WHERE t1.column1 = t2.column1;
 | 
Déplacer une clause  
FROM
  externe dans une sous-requête, comme ceci :  
au lieu de| 
SELECT * FROM t1WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
 | 
 Un autre exemple :| 
SELECT * FROM t1WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);
 | 
 au lieu de| 
SELECT (SELECT column1 + 5 FROM t1) FROM t2;
 | 
 | 
SELECT (SELECT column1 FROM t1) + 5 FROM t2;
 | 
Utiliser une sous-requête de ligne plutôt qu'une corrélation.
Par exemple : 
au lieu de| 
SELECT * FROM t1WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
 | 
 | 
SELECT * FROM t1WHERE 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
 
Quelques optimisation que MySQL va prendre en charge lui-même :
 
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
 .
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  
par une recherche dans un index, que  
EXPLAIN
  décrira comme
une jointure de type spécial.| 
... IN (SELECT indexed_column FROM single_table ...)
 | 
MySQL va améliorer les expressions de la forme 
avec une expression impliquant  
MIN
  ou  
MAX
  (à moins d'une
valeur  
NULL
  ou d'ensembles  
SET
  vides). Par exemple,| 
valeur {ALL|ANY|SOME} {> | < | >= | <=} (sous-requête non-correllée)
 | 
 revient à| 
WHERE 5 > ALL (SELECT x FROM t)
 | 
 | 
WHERE 5 > (SELECT MAX(x) FROM t)
 | 
 |