2010-09-24 13 views
118

Background: ho una query relativa alle prestazioni che vorrei eseguire e non mi interessa le letture sporche.SQL Server NOLOCK e join

La mia domanda è; Se sto usando join, devo specificare l'hint NOLOCK anche su quelli?

Ad esempio; è:

SELECT * FROM table1 a WITH (NOLOCK) 
INNER JOIN table2 b WITH (NOLOCK) ON a.ID = b.ID 

Equivalente a:

SELECT * FROM table1 a WITH (NOLOCK) 
INNER JOIN table2 b ON a.ID = b.ID 

O avrò bisogno di specificare il (NOLOCK) suggerimento su join per garantire non sto bloccare la tabella unita?

risposta

116

Non affronterò l'argomento READ UNCOMMITTED, solo la tua domanda originale.

Sì, è necessario WITH(NOLOCK) su ogni tabella del join. No, le tue domande non sono le stesse.

Prova questo esercizio. Inizia una transazione e inserisci una riga in table1 e table2. Non eseguire ancora il commit o il rollback della transazione.A questo punto, la prima query verrà restituita correttamente e includerà le righe non salvate; la seconda query non verrà restituita perché table2 non ha l'hint WITH(NOLOCK) su di esso.

+1

grazie per la risposta concisa, proprio quello che stavo cercando in questo caso. – DanP

14

Ero abbastanza sicuro che è necessario specificare il NOLOCK per ogni JOIN nella query. Ma la mia esperienza era limitata a SQL Server 2005.

Quando ho cercato MSDN solo per confermare, non ho trovato nulla di definito. Le dichiarazioni di seguito sembrano farmi pensare, che per il 2008, i tuoi due dichiarazioni di cui sopra sono equivalenti se per il 2005 non è il caso:

[SQL Server 2008 R2]

Tutto bloccare suggerimenti vengono propagati a tutte le tabelle e le viste che sono accessibili dal piano di query, incluse le tabelle e le viste a cui si fa riferimento in una vista. Inoltre, SQL Server esegue i controlli di coerenza del blocco corrispondenti.

[SQL Server 2005]

In SQL Server 2005, tutti i suggerimenti di blocco vengono propagati a tutti i tavoli e le viste cui si fa riferimento in una vista. Inoltre, SQL Server esegue i controlli di coerenza del blocco corrispondenti.

Inoltre, punto da notare - e questo vale sia per il 2005 e il 2008:

La tabella suggerimenti sono ignorati se la tabella non è accessibile dal piano di query. Ciò potrebbe essere causato dall'ottimizzatore che sceglie di non accedere affatto alla tabella o dal fatto che si accede a una vista indicizzata. In quest'ultimo caso, è possibile impedire l'accesso a una vista indicizzata utilizzando il suggerimento di query OPTION (EXPAND VIEWS).

+0

@In Sane: Interessante ... grazie per quello ... Suppongo di non farmi del male includendolo nelle JOIN, anche se non è del tutto necessario? La documentazione su NOLOCK è piuttosto scarsa come hai detto; Ho avuto difficoltà a trovare qualcosa di conclusivo da solo. – DanP

+2

@InSane: da dove hai preso queste informazioni? Sembra andare contro la risposta accettata. –

+0

@notfed - refer technet link http://technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - è possibile modificare la versione del database in alto per confrontare lo stesso articolo per diverse versioni di db – InSane

8

Nessuno dei due. Si imposta il livello di isolamento su READ UNCOMMITTED che è sempre meglio che fornire suggerimenti di blocco individuali. O, meglio ancora, se ti interessano dettagli come consistency, usa snapshot isolation.

+0

@Remus: Non sono sicuro di poter utilizzare READ UNCOMMITTED nel mio caso perché accedo alla connessione tramite NHibernate per eseguire una chiamata ADO.NET raw speciale; può essere specificato in linea nella query o obbedirà al livello di transazione presente nella transazione NHibernate? – DanP

+0

Includi la chiamata in 'using (TransactionScope scope = new TransactionScope (..., TransactionOptions) {...}' e imposta 'IsolationLevel' sulle opzioni: http://msdn.microsoft.com/en-us/ library/system.transactions.transactionoptions.isolationlevel.aspx –

+0

@Remus: Sfortunatamente, la gestione delle transazioni è gestita ad un livello molto più alto di questo, quindi non è nemmeno un'opzione. – DanP