Quand utiliser les sous-requêtes SQL versus une jointure standard?
je travaille sur la réécriture de certaines requêtes SQL mal écrites et ils utilisent trop les sous-requêtes. Je suis à la recherche de pratiques exemplaires concernant l'utilisation de sous-requêtes.
Toute aide serait appréciée.
3 réponses
les sous-séries sont généralement bien sauf si elles sont sous-séries dépendantes ( sous-séries corrélées). Si vous utilisez uniquement des sous-séries indépendantes et qu'elles utilisent des index appropriés, elles doivent être exécutées rapidement. Si vous avez une sous-requête dépendante, vous pourriez rencontrer des problèmes de performance parce qu'une sous-requête dépendante doit typiquement être exécutée une fois pour chaque ligne de la requête externe. Donc si votre requête externe a 1000 lignes, le sous-jeu sera lancé 1000 temps. D'autre part, un sous-produit indépendant ne doit généralement être évalué qu'une seule fois.
si vous n'êtes pas sûr de ce que signifie une sous - requête dépendante ou indépendante voici une règle empirique-si vous pouvez prendre la sous-requête, l'enlever de son contexte, l'exécuter, et obtenir un jeu de résultats alors c'est un independent subquery
.
si vous obtenez une erreur de syntaxe parce qu'elle se réfère à certaines tables en dehors de la sous-requête alors son a dependent subquery
.
la règle générale a bien sûr quelques exception. Par exemple:
- de nombreux optimiseurs peuvent prendre une sous-commande dépendante et trouver un moyen de l'exécuter efficacement en tant que jointure. Par exemple, une requête non existante pourrait donner lieu à un plan de requête anti JOIN, de sorte qu'elle ne sera pas nécessairement plus lente que l'écriture de la requête avec une JOIN.
- MySQL a un bug lorsqu'une sous-requête indépendante à l'intérieur d'une expression IN est incorrectement identifiée comme une sous-requête dépendante et qu'un plan de requête sous-optimal est utilisé. C'est apparemment fixé dans les versions les plus récentes de MySQL.
si la performance est un problème, mesurez vos requêtes spécifiques et voyez ce qui fonctionne le mieux pour vous.
il n'y a pas de balle en argent ici. Chaque utilisation doit être évalué de façon indépendante. Il y a des cas où les sous-séries corrélées sont totalement inefficaces, celle ci-dessous est mieux écrite comme une JOIN
select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u
D'un autre côté, les requêtes EXISTS et non EXISTS l'emporteront sur les jointures.
select ...
where NOT EXISTS (.....)
Est normalement plus rapide que
select ...
FROM A LEFT JOIN B
where B.ID is null
pourtant, même ces généralisations peuvent être fausses pour n'importe quel schéma particulier et la distribution de données.
malheureusement, la réponse dépend beaucoup du serveur sql que vous utilisez. En théorie, les jointures sont meilleures d'un point de vue purement relationnel. Ils laissent le serveur faire la bonne chose sous le capot et leur donne plus de contrôle et donc à la fin peut être plus rapide. Si le serveur est bien implémenté. En pratique, certains serveurs SQL fonctionnent mieux si vous le piégez en optimisant ses requêtes via des sous-requêtes et autres.