2010-06-21 19 views
6

Sono curioso del modo più efficiente per eseguire query sull'esclusione su sql. Per esempio. Ci sono 2 tabelle (tabella A e tabella B) che possono essere unite su 1 colonna (col1). Voglio visualizzare i dati della tabellaA per tutte le righe che col1 non esiste nella tabellaB.SQL: confronto delle prestazioni per esclusione (Join vs Not in)

(Quindi, in altre parole, tableB contiene un sottoinsieme di col1 di tableA. E voglio visualizzare tableA, senza i dati che esiste in tableB)

Diciamo tableB ha 100 righe mentre tableA è gigantesco (più di 1 milione di righe). So che 'Non in (non esiste)' può essere usato ma forse ci sono modi più efficienti (meno tempo comp.) Per farlo. Io non forse con outer join?

I frammenti di codice e i commenti sono molto apprezzati.

+0

Che tipo di DBMS? SQL Server, MySQL, Oracle? Le funzionalità degli ottimizzatori di query in queste differenze. –

+0

Oracle. Sarò sorpreso se ci sono differenze di prestazioni significative rispetto a vari DBMS. – someone

+0

Sì, sarete sorpresi. :) – Unreason

risposta

7

Dipende dall'RDBMS. Per Microsoft SQL Server NOT EXISTS is preferred per OUTER JOIN in quanto può utilizzare il join Anti-Semi più efficiente.

Per Oracle Minus is apparently preferred a NON ESISTE (dove indicato)

Lei avrebbe bisogno di guardare i piani di esecuzione e decidere.

+0

Grazie per la risposta. DBMS che mi interessa è Oracle. Sei sicuro che Minus sia più efficiente di una query con join o la risposta di inflagranti? – someone

+0

@ masa44 No, per niente. Anche se la risposta di inflagranti usa EXCEPT che * è * Minus in Oracle. La raccomandazione era di guardare i piani di esecuzione. –

+1

+1 per raccomandare di indagare sui piani di esecuzione (su dati reali con statistiche aggiornate). Anche la domanda è quali indici sono presenti. – Unreason

1

Le domande sono state poste più volte. Il modo più veloce è spesso di fare questo:

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

Come tutta la giunzione può essere fatto su indici, in cui utilizzano NOT IN generalmente non si può.

+0

Grazie per la risposta. Non sono riuscito a trovare le domande precedenti. – someone

+0

Questo per esempio penso sia simile: http://stackoverflow.com/questions/3074862/deleting-all-records-of-a-table-that-are-non-referenced-from-another-table/3074873#3074873 –

+0

Sì, è simile. Ma è difficile trovare questa domanda perché manca di descrizioni e tag dettagliati.Lo sai perché hai risposto a quello due giorni fa :) – someone

3

Io preferisco usare

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

Credo che questo sarà più veloce, come si sta utilizzando il vincolo FK (fornendo avete loro naturalmente)

dati del campione:

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

Grazie per la risposta, ma questa soluzione non funziona per me. Una ragione è che Col1 non può essere nullo (tableB ha solo Col1). Quindi la tua soluzione non mi dà risultati. – someone

+0

@ Masa44 - Sei sicuro? Funziona per me bene. Ho aggiunto alcuni dati di test come esempio. – codingbadger

+0

L'unione sinistra non è spesso il modo più veloce per molti database. – HLGEM

-1

Non c'è una risposta corretta a questa domanda. Ogni RDBMS ha Query Optimizer che determinerà il miglior piano di esecuzione in base agli indici disponibili, alle statistiche della tabella (numero di righe, selettività dell'indice), condizione di join, condizione della query, ...

Quando hai query relativamente semplici come nella tua domanda , ci sono spesso diversi modi per ottenere risultati in SQL. Ogni RDBMS che rispetti se stesso riconoscerà la tua intenzione e creerà lo stesso piano di esecuzione, indipendentemente dalla sintassi utilizzata (subquery con operatore IN o EXISTS, query con JOIN, ...)

Quindi, la soluzione migliore qui è scrivere più semplice query che funziona e quindi controllare il piano di esecuzione.
Se questa soluzione non è accettabile, dovresti cercare di trovare una query migliore.

+0

No, i database non generano lo stesso piano per tipi di query differenti che hanno lo stesso set di risultati. Se si guarda fornitore per fornitore, scoprirai quali sono i modi più efficienti per eseguire determinati tipi di query. – HLGEM

+0

@HLGEM Ovviamente non hai mai guardato i piani di esecuzione in Oracle nella situazione descritta in questione. – zendar

+0

NO I l; ook ai piani di esecuzione in SQL server in cui esiste un'enorme differenza tra approcci così diversi alla stessa query. E sapendo che so quale tipo provare prima. Scrivi la domanda più semplice è solo un cattivo consiglio. "Ogni RDBMS che rispetti se stesso riconoscerà la tua intenzione e creerà lo stesso piano di esecuzione, indipendentemente dalla sintassi che usi" è semplicemente falso. – HLGEM

Problemi correlati