2010-05-06 7 views
14

Quelle est l'importance d'éviter les requêtes imbriquées? J'ai toujours appris à les éviter comme un fléau. Mais ils sont la chose la plus naturelle pour moi. Lorsque je conçois une requête, la première chose que j'écris est une requête imbriquée. Ensuite, je le convertis en jointures, ce qui prend parfois beaucoup de temps pour bien faire. Et donne rarement une grande amélioration des performances (parfois il le fait)Comment éviter les requêtes imbriquées

Alors, ils sont vraiment si mauvais. Existe-t-il un moyen d'utiliser des requêtes imbriquées sans tables temporaires et filesort

+1

Je voudrais également savoir ceci. – IsmailS

+1

Je doute que ce soit important du point de vue de la performance, au moins dans MS SQL Server. MySQL n'est pas aussi intelligent ... – Thorarin

Répondre

6

Cela dépend vraiment, j'ai eu des situations où j'amélioré certaines requêtes en utilisant les sous-requêtes.

Les facteurs que je connais sont:

  • si la sous-requête utilise des champs de requête externe pour la comparaison ou non (correlated ou non)
  • si la relation entre la requête externe et sous requête est couvert par index
  • si aucun index utilisable sur les jointures et la sous-requête n'est pas corrélée et renvoie un petit résultat il peut être plus rapide de l'utiliser
  • J'ai également rencontré des situations où transformer une requête qui utilise order by dans aq uery qui ne l'utilise pas et que le transformer en une sous-requête simple et genre qui améliore les performances dans une base MySQL

Quoi qu'il en soit, il est toujours bon de tester différentes variantes (avec SQL_NO_CACHE s'il vous plaît), et transformer les requêtes corrélées dans les jointures est une bonne pratique.

J'irais même jusqu'à dire que c'est une pratique très utile. Il peut être possible que si les requêtes corrélées sont les premières qui vous viennent à l'esprit que vous ne pensiez pas en termes d'opérations d'ensemble, mais principalement en termes d'opérations procédurales et en traitant des bases de données relationnelles, il est très utile de adopter pleinement la perspective définie sur le modèle de données et les transformations qui y sont apportées.

EDIT: procédure vs Relational
Penser en termes d'opérations réglées contre la procédure se résume à l'équivalence dans certaines expressions d'algèbre ensemble, par exemple la sélection d'une union est équivalente à l'union des sélections. Il n'y a pas de différence entre les deux.Mais lorsque vous comparez les deux procédures, telles que l'application des critères de sélection à chaque élément d'une union avec union et application de la sélection, les deux sont des procédures nettement différentes, qui peuvent avoir des propriétés très différentes (par exemple utilisation du processeur). , E/S, mémoire). L'idée derrière les bases de données relationnelles est que vous n'essayez pas de décrire comment obtenir le résultat (procédure), mais seulement ce que vous voulez, et que le système de gestion de base de données décidera du meilleur chemin (procédure) pour remplir votre demande. C'est pourquoi SQL est appelé 4th generation language (4GL). L'un des trucs qui vous aide à faire cela est de vous rappeler que les tuples n'ont pas d'ordre inhérent (les éléments du set ne sont pas ordonnés). Un autre est de réaliser que l'algèbre relationnelle est assez complète et permet de traduire des requêtes directement en SQL (si la sémantique de votre modèle représente bien l'espace problème, ou en d'autres termes si le sens de vos tables et relations est à droite, ou en d'autres termes si votre base de données est bien conçue).

Par conséquent, vous n'avez pas à penser comment, seulement quoi. Dans votre cas, c'était juste la préférence sur les requêtes corrélées, il se peut donc que je ne vous dise rien de nouveau, mais vous avez souligné ce point, d'où le commentaire. Je pense que si vous étiez complètement à l'aise avec toutes les règles qui transforment les requêtes d'une forme en une autre (rules comme la distribution), vous ne préféreriez pas les sous-requêtes corrélées (que vous verriez toutes les formes égales). Remarque: le contexte théorique, important pour la conception de la base de données, est différent: les réécritures équivalentes d'une requête ne sont pas forcément exécutées rapidement, les clés primaires groupées font que les tables héritent de l'ordre sur le disque, etc. .. mais ces écarts ne sont que des déviations, le fait que toutes les requêtes équivalentes ne s'exécutent pas aussi vite est une imperfection du SGBD réel et non des concepts qui le sous-tendent)

+0

Avez-vous un exemple de "penser en termes d'opérations d'ensemble" par rapport à "en termes d'opérations procédurales". – Midhat

+0

@Midhat: commenté dans la réponse (EDIT). Désolé si ce n'est pas ce que vous vouliez, avez-vous cherché des exemples plus pratiques ou une explication comme ci-dessus? – Unreason

+0

merci. beaucoup mieux maintenant – Midhat

1

Je ne sais pas à quoi cela ressemble en MySQL 5.1 ou 5.5, mais en 5.0.x les requêtes imbriquées ont généralement des performances horribles, car MySQL effectue une sous-requête pour chaque ligne récupérée de la requête principale. Ce n'est probablement pas le cas pour des bases de données plus matures comme MsSQL, qui peut réécrire en interne des requêtes imbriquées dans des jointures, mais je n'ai jamais utilisé MsSQL donc je ne sais pas avec certitude.

http://dev.mysql.com/doc/refman/5.0/en/rewriting-subqueries.html

Il est vrai aussi que dans certaines occasions, il est non seulement possible de réécrire une requête sans sous-requête, mais il peut être plus efficace d'utiliser certaines de ces techniques plutôt que d'utiliser sous-requêtes. - ce qui est une déclaration plutôt drôle, compte tenu que pour moi jusqu'à présent tous les sous-requêtes faire l'exploration de la base de données.

Subqueries vs joins

Questions connexes