SQL Joins Vs sous-requêtes SQL (Performance)?

Je souhaite savoir si j’ai une requête de jointure quelque chose comme ça –

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id 

et une sous-question quelque chose comme ça –

 Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept) 

Quand je considère la performance, laquelle des deux requêtes serait plus rapide et pourquoi ?

Y a-t-il un moment où je devrais préférer l’un à l’autre?

Désolé si c’est trop sortingvial et demandé avant mais je suis confus à ce sujet. En outre, ce serait bien si vous pouviez me suggérer des outils que je devrais utiliser pour mesurer les performances de deux requêtes. Merci beaucoup!

J’attendais que la première requête soit plus rapide, principalement parce que vous avez une équivalence et un JOIN explicite. Dans mon expérience, IN est un opérateur très lent, puisque SQL l’évalue normalement comme une série de clauses WHERE séparées par “OR” ( WHERE x=Y OR x=Z OR... ).

Comme avec ALL THINGS SQL, votre kilométrage peut varier. La vitesse dépendra beaucoup des index (avez-vous des index sur les deux colonnes d’ID? Cela aidera beaucoup, entre autres).

La seule façon REELLE de dire avec une certitude de 100% plus rapide est d’activer le suivi des performances (les statistiques IO sont particulièrement utiles) et de les exécuter toutes les deux. Veillez à effacer votre cache entre les exécutions!

Eh bien, je crois que c’est une question “Old but Gold”. La réponse est: “ça dépend!”. Les performances sont un sujet tellement délicat qu’il serait trop idiot 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: Ici 1 ici 2 ici 3

J’ai une table avec 50000 éléments, le résultat que je cherchais était 739 éléments.

Au début, ma question était la suivante:

 SELECT p.id, p.fixedId, p.azienda_id, p.categoria_id, p.linea, p.tipo, p.nome FROM prodotto p WHERE p.azienda_id = 2699 AND p.anno = ( SELECT MAX(p2.anno) FROM prodotto p2 WHERE p2.fixedId = p.fixedId ) 

et il a fallu 7,9s pour exécuter.

Ma question est enfin celle-ci:

 SELECT p.id, p.fixedId, p.azienda_id, p.categoria_id, p.linea, p.tipo, p.nome FROM prodotto p WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN ( SELECT p2.fixedId, MAX(p2.anno) FROM prodotto p2 WHERE p.azienda_id = p2.azienda_id GROUP BY p2.fixedId ) 

et il a fallu 0,0256s

Bon SQL, bon.

Commencez par examiner les plans d’exécution pour voir les différences d’interprétation du serveur SQl. Vous pouvez également utiliser Profiler pour exécuter les requêtes plusieurs fois et obtenir la différence.

Je ne m’attendrais pas à ce qu’ils soient si horriblement différents, où vous pouvez être réel, les gains de performances importants dans l’utilisation des jointures au lieu des sous-requêtes sont lorsque vous utilisez des sous-requêtes corrélées.

EXISTS est souvent meilleur que l’un de ces deux et lorsque vous parlez des jointures de gauche où vous voulez tous les enregistrements qui ne sont pas dans la table de jointure de gauche, alors NOT EXISTS est souvent un meilleur choix.

Les deux requêtes peuvent ne pas être sémantiquement équivalentes. Si un employé travaille pour plusieurs départements (possible dans l’entreprise pour laquelle je travaille, cela impliquerait que votre table n’est pas complètement normalisée) alors la première requête renverrait des lignes en double alors que la seconde ne le ferait pas. Pour que les requêtes soient équivalentes dans ce cas, le DISTINCT clé DISTINCT doit être ajouté à la clause SELECT , ce qui peut avoir un impact sur les performances.

Notez qu’il existe une règle de conception qui indique 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 départements.

Les performances sont basées sur la quantité de données que vous exécutez sur …

Si c’est moins de données autour de 20k. JOIN fonctionne mieux

Si les données ressemblent plus à 100 k + alors IN fonctionne mieux.

Si vous n’avez pas besoin des données de l’autre table, IN est bien, mais il vaut mieux toujours choisir EXISTS.

Tous ces critères que j’ai testés et les tableaux ont des index corrects.

La performance devrait être la même; Il est beaucoup plus important d’appliquer les index et les regroupements corrects sur vos tables (il existe de bonnes ressources sur ce sujet).

(Édité pour refléter la question mise à jour)

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.

Je sais que c’est un ancien message, mais je pense que c’est un sujet très important, en particulier de nos jours, où nous avons des enregistrements de 10 millions et plus et des téraoctets de données.

Je vais également prendre en compte les observations suivantes. J’ai environ 45M enregistrements dans ma table ([data]), et environ 300 enregistrements dans ma table [cats]. J’ai une longue indexation pour toutes les questions que je vais aborder.

Considérons l’exemple 1:

 UPDATE d set category = c.categoryname FROM [data] d JOIN [cats] c on c.id = d.catid 

par rapport à l’exemple 2:

 UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid) FROM [data] d 

L’exemple 1 a pris environ 23 minutes pour fonctionner. 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 de i / o @ 1 Go / sec (c’est-à-dire des octets, pas des bits), donc mes index sont vraiment rapides aussi. Donc, cela peut affecter la vitesse aussi dans votre situation

S’il s’agit d’un nettoyage de données unique, il vaut probablement mieux le laisser fonctionner et terminer. J’utilise TOP (10000) et vois combien de temps cela prend et multiplie par le nombre d’enregistrements avant que je n’atteigne la grande requête.

Si vous optimisez les bases de données de production, je vous suggère fortement de pré-traiter les données, c’est-à-dire d’utiliser des déclencheurs ou un courtier pour asynchroniser les enregistrements, afin que l’access en temps réel récupère les données statiques.

La requête finale incluait azienda_id dans la sous-requête corelated, mais votre requête initiale n’incluait pas azienda_id dans la sous-requête corelated. La comparaison n’est donc pas la même.

J’ai testé la théorie de HLGEM en comparant les nombres de «statistiques d’utilisation des clients», il s’avère que «n’existe pas» est rapide que «joindre à gauche» lorsque vous recherchez tous les enregistrements qui ne figurent pas dans la table de gauche.

La beauté de SQL réside dans ses nombreuses manières de l’écrire, et les performances ne dépendent pas uniquement de la jointure ou de la sous-requête, mais du jeu de résultats que vous recherchez.