Question

J'ai besoin de conseils concernant les performances de sous-sélection dans MySQL. Pour une raison que je ne peux pas modifier, je ne peux pas utiliser JOIN pour créer un filtre quesry, je ne peux ajouter qu'une autre clause AND dans WHERE.

Quelle est la performance de:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

comparé à:

select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Notez qu'il existe un nombre relativement petit de projets whete is_template = 1 et qu'il peut y en avoir un grand nombre de projets où is_template < > 1.

Existe-t-il un autre moyen d'obtenir le même résultat sans sous-sélection si je ne peux rien changer à part filtrer?

Était-ce utile?

La solution

Je pense que le second est plus efficace car il ne nécessite qu'une seule sélection, mais pour être sûr, vous devez EXPLAQUER chaque requête et vérifier les résultats.

EXPLAIN select tasks.*
from tasks
where 
  some criteria
  and task.project_id not in (select id from project where project.is_template = 1);

EXPLAIN select tasks.*
from tasks, project
where
  some criteria
  and task.project_id = project.id and project.is_template <> 1;

Autres conseils

L’importance de la différence entre les deux pourrait dépendre grandement de & "certains critères &"; est et quelles sont les possibilités d'utiliser les index qu'il fournit. Mais notez qu'ils ne sont pas équivalents en termes de résultats s'il y a des tâches qui n'ont pas de projets. La seconde est équivalente à ceci:

select tasks.*
from tasks
where 
  some criteria
  and task.project_id in (select id from project where project.is_template <> 1);

Je pense que le premier pourrait mieux évoluer:

Lorsque vous faites une jointure, mysql crée en interne une sorte de table temporaire composée des deux tables jointes selon les conditions de jointure spécifiées. Vous ne donnez pas de condition de jointure, vous créerez donc une table temporaire avec toutes les tâches répertoriées pour tous les projets. Je suis à peu près sûr (mais vérifiez avec l'outil d'explication) qu'il le fait avant d'appliquer toute clause where.

Résultat: s'il y en a 10, il aura 10 * 10 lignes = 100. Vous pouvez voir à quel point cela devient important à mesure que les chiffres augmentent. Il applique ensuite l’emplacement à cette table temporaire.

En revanche, la sous-requête ne sélectionne que les lignes pertinentes de chaque tableau.

Mais à moins que la mise à l'échelle ne soit une préoccupation, je ne pense pas que cela compte vraiment.

Évitez les sous-requêtes telles que celle des fléaux dans les versions de MySQL < 6.0, et je doute que vous utilisiez la 6.0 car elle est encore en phase alpha de développement. Autant que je sache, l’optimiseur MySQL ne gère pas bien les sous-requêtes. La refonte de l'optimiseur pour la version 6.0 a pris beaucoup de travail, mais les sous-requêtes fonctionnent beaucoup mieux maintenant, mais ces modifications ne se sont pas répercutées dans la série 5.0 ou 5.1.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top