Je souhaite savoir si j'ai une requête de jointure quelque chose comme ceci -
Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id
et une sous - requête quelque chose comme ça -
Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)
Lorsque je considère les performances, laquelle des deux requêtes serait la plus rapide et pourquoi ?
Y a-t-il aussi un moment où je devrais préférer l'un à l'autre?
Désolé si c'est trop trivial et demandé avant mais je suis confus à ce sujet. De plus, ce serait formidable si vous pouviez me suggérer des outils que je devrais utiliser pour mesurer les performances de deux requêtes. Merci beaucoup!
Réponses:
Je m'ATTENDrais à ce que la première requête soit plus rapide, principalement parce que vous avez une équivalence et une jointure explicite. D'après mon expérience,
IN
c'est un opérateur très lent, puisque SQL l'évalue normalement comme une série deWHERE
clauses séparées par "OR" (WHERE x=Y OR x=Z OR...
).Comme pour ALL THINGS SQL cependant, votre kilométrage peut varier. La vitesse dépendra beaucoup des index (avez-vous des index sur les deux colonnes ID? Cela aidera beaucoup ...) entre autres.
La seule VRAIE façon de savoir avec 100% de certitude ce qui est plus rapide est d'activer le suivi des performances (IO Statistics est particulièrement utile) et de les exécuter tous les deux. Assurez-vous de vider votre cache entre les exécutions!
la source
Eh bien, je crois que c'est une question «ancienne mais or». La réponse est: "Cela dépend!". Les performances sont un sujet si délicat qu'il serait trop ridicule de dire: "N'utilisez jamais de sous-requêtes, rejoignez toujours". Dans les liens suivants, vous trouverez quelques bonnes pratiques de base que j'ai trouvées très utiles:
J'ai une table avec 50000 éléments, le résultat que je recherchais était de 739 éléments.
Ma question au début était la suivante:
et il a fallu 7,9 secondes pour s'exécuter.
Ma question est enfin la suivante:
et il a fallu 0,0256 s
Bon SQL, bon.
la source
Commencez à regarder les plans d'exécution pour voir les différences dans la façon dont le serveur SQl les interprétera. Vous pouvez également utiliser Profiler pour exécuter les requêtes plusieurs fois et obtenir la différence.
Je ne m'attendrais pas à ce que ceux-ci soient si horriblement différents, où vous pouvez obtenir des gains de performances réels et importants en utilisant des jointures au lieu de sous-requêtes lorsque vous utilisez des sous-requêtes corrélées.
EXISTS est souvent meilleur que l'un ou l'autre de ces deux et lorsque vous parlez de jointures à gauche où vous voulez que tous les enregistrements ne soient pas dans la table de jointure de gauche, NOT EXISTS est souvent un bien meilleur choix.
la source
Les performances sont basées sur la quantité de données sur lesquelles vous exécutez ...
Si c'est moins de données autour de 20k. JOIN fonctionne mieux.
Si les données ressemblent plus à 100k +, IN fonctionne mieux.
Si vous n'avez pas besoin des données de l'autre table, IN est bon, mais il est toujours préférable d'opter pour EXISTS.
J'ai testé tous ces critères et les tables ont des index appropriés.
la source
La performance doit être la même; il est beaucoup plus important d'avoir les bons index et le clustering appliqués sur vos tables (il existe de bonnes ressources sur ce sujet).
(Modifié pour refléter la question mise à jour)
la source
Les deux requêtes peuvent ne pas être sémantiquement équivalentes. Si un employé travaille pour plus d'un département (possible dans l'entreprise pour laquelle je travaille; certes, cela impliquerait que votre table n'est pas entièrement normalisée), la première requête renverrait des lignes en double alors que la deuxième requête ne le ferait pas. Pour rendre les requêtes équivalentes dans ce cas, il
DISTINCT
faudrait ajouter le mot - clé à laSELECT
clause, ce qui peut avoir un impact sur les performances.Notez qu'il existe une règle de conception empirique qui stipule qu'une table doit modéliser une entité / classe ou une relation entre entités / classes, mais pas les deux. Par conséquent, je vous suggère de créer un troisième tableau, par exemple
OrgChart
, pour modéliser la relation entre les employés et les ministères.la source
Je sais que c'est un ancien message, mais je pense que c'est un sujet très important, surtout de nos jours où nous avons plus de 10 millions d'enregistrements et parlons de téraoctets de données.
Je vais également appuyer les observations suivantes. J'ai environ 45 millions d'enregistrements dans ma table ([data]) et environ 300 enregistrements dans ma table [cats]. J'ai une indexation complète pour toutes les requêtes dont je vais parler.
Prenons l'exemple 1:
par rapport à l'exemple 2:
L'exemple 1 a duré environ 23 minutes. L'exemple 2 a pris environ 5 minutes.
Je conclurais donc que la sous-requête dans ce cas est beaucoup plus rapide. Bien sûr, gardez à l'esprit que j'utilise des disques SSD M.2 capables d'entrées / sorties à 1 Go / s (ce sont des octets et non des bits), donc mes index sont également très rapides. Cela peut donc également affecter les vitesses dans votre situation
S'il s'agit d'un nettoyage de données ponctuel, il est probablement préférable de le laisser s'exécuter et de terminer. J'utilise TOP (10000) et je vois combien de temps cela prend et je multiplie par le nombre d'enregistrements avant de lancer la grande requête.
Si vous optimisez des bases de données de production, je suggérerais fortement de pré-traiter les données, c'est-à-dire d'utiliser des déclencheurs ou un job-broker pour asynchroniser les enregistrements de mise à jour, de sorte que l'accès en temps réel récupère les données statiques.
la source
Vous pouvez utiliser un plan d'explication pour obtenir une réponse objective.
Pour votre problème, un filtre Exists serait probablement le plus rapide.
la source