Domanda

Supponiamo che io ho due tabelle collegate (uno ha una chiave esterna per l'altro):

CREATE TABLE Document (
  Id INT PRIMARY KEY,
  Name VARCHAR 255
)

CREATE TABLE DocumentStats (
  Id INT PRIMARY KEY,
  DocumentId INT, -- this is a foreign key to table Document
  NbViews INT
)

Lo so, questo non è il modo più intelligente di fare le cose, ma questo è l'esempio meglio che ho potuto trovare.

Ora, voglio ottenere tutti i documenti che hanno più di 500 punti di vista. Le due soluzioni che mi vengono in mente sono:

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

o

SELECT *
FROM Document
INNER JOIN DocumentStats
ON Document.Id = DocumentStats.Id
WHERE DocumentStats.NbViews > 500

Le due interrogazioni equivalente, o c'è un modo che è di gran lunga migliore rispetto agli altri? Se sì, perché?

Sono consapevole che il mio esempio non è perfetto, e che le query potrebbe essere necessario un po 'di messa a punto, ma spero che hai il punto;)

!

EDIT: come richiesto nelle risposte, questa domanda mirava a MSSQL, ma sarei interessato a sapere se è diversa per gli altri motori DB (MySQL, ecc ...)

È stato utile?

Soluzione

In teoria, no, non dovrebbe essere più veloce. Query Optimizer dovrebbe essere in grado di generare un piano di esecuzione identico. Tuttavia, alcuni motori DB possono produrre migliori piani di esecuzione di uno di loro (non probabile che accada per una semplice query tale, ma per quelli abbastanza complessi). Si dovrebbe provare entrambi e vedere (sul vostro motore DB).

Altri suggerimenti

Performance di "JOIN" contro "WHERE" ... tutto dipende dal modo in cui il motore di database è in grado di ottimizzare la query per voi. Si terrà conto tutti gli indici che potreste avere sulle colonne da restituire e considerare che le prestazioni di WHERE e JOIN clausole anche venire giù al file fisico database stesso e il suo livello di frammentazione e anche la tecnologia di storage si utilizza per memorizzare i file di database su .

Server MSSql esegue query nel seguente ordine (questo dovrebbe darvi un'idea delle funzioni del WHERE e JOIN clausole)

Microsoft Sql ordine processo di query Server

il seguente è preso dal eccellente serie di libri su Microsoft SQL Server, Inside Microsoft SQL Server 2005: T-SQL Interrogazione che si trova qui

  

(Punto 8) SELECT (Passo 9) DISTINCT (Step 11)    
  (Fase 1) FROM left_table
(Fase 3)    join_type ENTRA right_table
(Fase 2) ON join_condition
(Fase 4) DOVE    where_condition
(Passo 5) GROUP BY group_by_list
(Fase 6) con [CUBE | ROLLUP]
(Passo 7) Avendo    having_clause
(Punto 10) ORDER BY order_by_list

Non v'è alcun modo per rispondere correttamente questo senza limitare a un database di destinazione.

Per MS-SQL entrambe le query provocano gli stessi piani di esecuzione, ma tenere a mente:

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

è davvero rischioso dal momento che è facile dimenticare la condizione di join nella clausola WHERE e finire con un brutto cross join.

In MySQL almeno, saranno entrambi ottimizzati per la stessa query.

Si tratta di uno "standard" per utilizzare la sintassi INNER JOIN, anche se praticamente equivalenti. Il motivo principale dovrebbe essere utilizzato sia a fini di chiarezza e di mobilità perché è coerente con OUTER JOIN sintassi.

Quando si utilizza SQLite:. L'cui sintassi è leggermente più veloce perché Sqlite traduce prima della join-sintassi in cui sintassi prima di eseguire la query

Se stai parlando specificamente su SQL Server, allora dovete assolutamente utilizzare la sintassi INNER JOIN. Oltre ad essere (avviso parere personale!) Più facile da leggere e più chiara negli intenti, non v'è, come di SQL Server 2005, non sintassi equivalente per outer join. Il * = e = * la sintassi non è supportata di default nel 2005 - è necessario abilitare una modalità di compatibilità per sostenerlo. Si finirà per essere rimosso, possibilmente non appena la prossima release (o forse no!)

Ciò significa:

  • Se è necessario modificare una query da join interno a outer join, è necessario o riscrivere (argh) o attivare la modalità compat (bleah)
  • Senza modalità compat, non è possibile essere coerente con il modo di implementare diversi tipi di join (interno vs esterno), rendendo per un incubo di manutenzione (e, dove i due sono combinati in una query, un comportamento che è non- intuitivo).

Si noti anche che, contrariamente alla credenza popolare, i due sono non equivalente. Alcune cose sono molto più scomodo, e alcuni non sono semplicemente possibili. Kalen Delaney di All'interno di SQL Server 2000 copre alcuni esempi; Non so se le edizioni più recenti fanno, perché che la sintassi di join è sconsigliato in ogni caso.

esplicita unisce sono più facili da mantenere, come l'intento della query è molto più chiara. Inoltre essi non sono soggetti a croce accidentale si unisce quindi se avete un cross join nella query, il manutentore sa che era destinato ad essere lì.

Se avete mai bisogno di utilizzare outer join, si dovrebbe sapere che l'* = sintassi è obsoleta in SQL Server e sarà presto rimossa. Inoltre attualmente non funziona come previsto per tutto il tempo e non può dare risultati corretti e quindi mai da utilizzare. Miscelazione esterna esplicita unisce e dove si unisce la clausola (implicito si unisce) fa una query molto più difficile per un manutentore di leggere e comprendere.

In MSSQL, entrambe le query sono compilati allo stesso piano di esecuzione, quindi non c'è alcuna differenza. E 'più di leggibilità -. Credo che il join è più facile da leggere, per cui uso che

Credo che non fa una differenza troppo. Per essere sicuri di poter controllare se il piano di spiegare di queste due query è identico. Per guardare il piano spiegare in MySQL si deve mettere la parola chiave "spiegare" prima dell'istruzione, ad esempio:

EXPLAIN
SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

Sono sicuro che esiste un equivalente in MSSQL troppo.

A proposito: Questo appare come questo è un 1:. Rapporto 1 in modo che avevo appena includere il nbviews attribuiscono direttamente nella tabella del documento, pertanto, è possibile salvare un join

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top