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.