SQL Server NOLOCK e join


153

Contesto: ho una query critica per le prestazioni che vorrei eseguire e non mi importa delle letture sporche.

La mia domanda è; Se sto usando i join, devo specificare il suggerimento NOLOCK anche su quelli?

Per 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 dovrò specificare il (NOLOCK)suggerimento sul join per assicurarmi di non bloccare la tabella unita?

Risposte:


166

Non affronterò l' READ UNCOMMITTEDargomento, 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 tua prima query tornerà correttamente e includerà le righe senza commit; la tua seconda query non verrà restituita perché table2 non ha il WITH(NOLOCK)suggerimento.


18

Ero abbastanza sicuro che è necessario specificare il NOLOCKper ciascuno JOINnella query. Ma la mia esperienza è stata limitata a SQL Server 2005.

Quando ho cercato MSDN solo per confermare, non sono riuscito a trovare nulla di definito. Le seguenti affermazioni sembrano farmi pensare che per il 2008 le vostre due affermazioni sopra riportate sono equivalenti, ma per il 2005 non è così:

[SQL Server 2008 R2]

Tutti i suggerimenti di blocco vengono propagati a tutte le tabelle e viste a cui accede il piano di query , comprese le tabelle e le viste a cui fa riferimento una vista. Inoltre, SQL Server esegue i controlli di coerenza dei blocchi corrispondenti.

[SQL Server 2005]

In SQL Server 2005, tutti gli hint di blocco vengono propagati a tutte le tabelle e viste a cui viene fatto riferimento in una vista. Inoltre, SQL Server esegue i controlli di coerenza dei blocchi corrispondenti.

Inoltre, tieni presente che ciò vale sia per il 2005 che per il 2008:

I suggerimenti per la tabella vengono ignorati se il piano di query non accede alla tabella. Ciò può essere causato dall'ottimizzatore che sceglie di non accedere affatto alla tabella o perché si accede invece a una vista indicizzata. In quest'ultimo caso, è possibile impedire l'accesso a una vista indicizzata utilizzando il OPTION (EXPAND VIEWS)suggerimento per la query.


@In Sane: Interessante ... grazie per quello ... Sto assumendo che non sto facendo alcun male includendolo nei JOIN, anche se non è del tutto necessario? La documentazione su NOLOCK è piuttosto scarsa come hai già 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.
Jay Sullivan,

1
@notfed - consultare il collegamento technet 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 del db
Jagmag

2
Il testo del 2005 parla di VISUALIZZAZIONI. Quindi, se fai "da myview con (nolock)", allora dice che nolock viene propagato a tutte le tabelle e viste coinvolte in myview (potresti avere 10 join lì). Non sono sicuro del significato esatto del testo del 2008 in quanto aggiunge "accesso al piano di query" oltre alle visualizzazioni.
Thierry_S,

9

Né. Si imposta il livello di isolamento suREAD UNCOMMITTED cui è sempre meglio che fornire singoli suggerimenti di blocco. O, meglio ancora, se ti interessano dettagli come la coerenza , usa l' isolamento dell'istantanea .


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

Termina la chiamata using (TransactionScope scope=new TransactionScope(..., TransactionOptions) {...}e imposta le IsolationLevelopzioni: msdn.microsoft.com/en-us/library/…
Remus Rusanu

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

Vedo. Quindi, per rispondere alla tua domanda: NOLOCK è un suggerimento per la tabella e come tale si applica al set di righe a cui viene aggiunto (tabella, vista, TVF ecc.). Se hai più set di righe uniti in una query, ognuno avrebbe bisogno del proprio suggerimento NOLOCK.
Remus Rusanu,

2
Ma hai considerato l'isolamento di un'istantanea? ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON;. I risultati sono spettacolari, poiché tutte le letture impegnate nella lettura normale si trasformano in letture istantanee, bloccate in modo libero ma coerente. Il costo è un aumento del tempdbcarico: msdn.microsoft.com/en-us/library/ms175492.aspx
Remus Rusanu
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.