2010-06-21 4 views
6

Je suis curieux sur la manière la plus efficace d'interroger l'exclusion sur sql. Par exemple. Il y a 2 tables (tableA et tableB) qui peuvent être jointes sur 1 colonne (col1). Je veux afficher les données de tableA pour toutes les lignes dont col1 n'existe pas dans la tableB.SQL: Comparaison des performances pour l'exclusion (Join vs Not in)

(Donc, en d'autres termes, tableB contient un sous-ensemble de col1 de tableA. Et je veux afficher tableA sans les données qui existe dans tableB)

Disons que tableB a 100 lignes tandis que tableA est gigantesque (plus que 1M lignes). Je sais que 'pas dans (pas existe)' peut être utilisé mais peut-être y at-il des moyens plus efficaces (moins de temps) pour le faire. Je ne suis peut-être pas avec des jointures externes?

Les extraits de code et commentaires sont très appréciés.

+0

Quel SGBD? SQL Server, MySQL, Oracle? Les capacités des optimiseurs de requête dans ceux-ci diffèrent. –

+0

Oracle. Je serai surpris s'il y a des différences de performance significatives sur divers SGBD. – someone

+0

Oui, vous serez surpris. :) – Unreason

Répondre

7

Dépend du SGBDR. Pour Microsoft SQL Server NOT EXISTS is preferred à l'OUTER JOIN car il peut utiliser la jointure Anti-Semi plus efficace.

Pour Oracle Minus is apparently preferred de NE PAS EXISTE (où approprié)

Vous auriez besoin de regarder les plans d'exécution et de décider.

+0

Merci pour la réponse. Le SGBD qui m'intéresse est Oracle. Etes-vous sûr que Minus est plus efficace qu'une requête avec join ou la réponse d'inflagranti? – someone

+0

@ masa44 Non, pas du tout. Bien que la réponse d'inflagranti utilise EXCEPT qui * est * Minus dans Oracle. La recommandation était d'examiner les plans d'exécution. –

+1

+1 pour avoir recommandé d'étudier les plans d'exécution (sur des données réelles avec des statistiques mises à jour). La question est également de savoir quels index sont présents. – Unreason

1

Les questions ont été posées plusieurs fois. La façon la plus rapide est souvent de le faire:

SELECT * FROM table1 
WHERE id in (SELECT id FROM table1 EXCEPT SELECT id FROM table2) 

Comme l'ensemble de rejoindre peut se faire sur les indices, où l'utilisation NOT IN ne peut généralement pas.

+0

Merci pour la réponse. Je n'ai pas pu trouver les questions précédemment posées. – someone

+0

Ceci par exemple je pense est similaire: http://stackoverflow.com/questions/3074862/deleting-all-records-of-a-table-that-are-not-referenced-from-another-table/3074873#3074873 –

+0

Oui, c'est similaire. Mais il est difficile de trouver cette question car il manque une description détaillée et des balises.Vous le savez parce que vous avez répondu à celui-ci il y a 2 jours :) – someone

3

Je préfère utiliser

Select a.Col1 
From TableA a 
Left Join TableB b on a.Col1 = b.Col1 
Where b.Col1 Is Null 

Je crois que ce sera plus rapide que vous êtes en utilisant la contrainte FK (à condition que vous les avez bien sûr)

données Exemple:

create table #a 
(
Col1 int 
) 
Create table #b 
(
col1 int 
) 

insert into #a 
Values (1) 
insert into #a 
Values (2) 
insert into #a 
Values (3) 
insert into #a 
Values (4) 

insert into #b 
Values (1) 
insert into #b 
Values (2) 


Select a.Col1 
From #a a 
Left Join #b b on a.col1 = b.Col1 
Where b.Col1 is null 
+0

Merci pour la réponse mais cette solution ne fonctionne pas pour moi. Une des raisons est que Col1 ne peut pas être nul (la tableB n'a que Col1). Donc, votre solution ne me donne aucun résultat. – someone

+0

@ Masa44 - Etes-vous sûr? Cela fonctionne pour moi bien. J'ai ajouté quelques données de test à titre d'exemple. – codingbadger

+0

La jointure à gauche n'est souvent pas le moyen le plus rapide pour de nombreuses bases de données. – HLGEM

-1

Il n'y a pas de réponse correcte à cette question. Chaque SGBDR a un optimiseur de requêtes qui déterminera le meilleur plan d'exécution basé sur les indices disponibles, les statistiques de table (nombre de lignes, sélectivité d'index), les conditions de jointure, etc. , il y a souvent plusieurs façons d'obtenir des résultats en SQL. Tout RDBMS respectueux de soi reconnaîtra votre intention et créera le même plan d'exécution, quelle que soit la syntaxe utilisée (sous-requêtes avec opérateur IN ou EXISTS, requête avec JOIN, ...)

Donc, la meilleure solution ici est d'écrire le plus simple requête qui fonctionne, puis vérifiez le plan d'exécution.
Si cette solution n'est pas acceptable, vous devriez essayer de trouver une meilleure requête.

+0

Non, les bases de données ne généreront pas le même plan pour différents types de requêtes qui ont le même jeu de résultats. Si vous recherchez un fournisseur par fournisseur, vous découvrirez quels sont les moyens les plus efficaces de faire des types spécifiques de requêtes. – HLGEM

+0

@HLGEM Vous n'avez évidemment jamais regardé les plans d'exécution dans Oracle dans la situation décrite à la question. – zendar

+0

NO Je ne vois pas les plans d'exécution dans le serveur SQL où il existe une différence énorme entre ces différentes approches de la même requête. ET sachant que je sais quel type essayer en premier. Ecrire la requête la plus simple est juste un mauvais conseil. ANd "Tout SGBDR respectueux de soi reconnaîtra votre intention et créera le même plan d'exécution, quelle que soit la syntaxe utilisée" est tout simplement faux. – HLGEM

Questions connexes