2010-09-24 15 views
118

Antecedentes: tengo una consulta de rendimiento crítico que me gustaría ejecutar y no me importan las lecturas sucias.SQL Server NOLOCK y se une a

Mi pregunta es; Si estoy usando uniones, ¿tengo que especificar la sugerencia de NOLOCK en esas también?

Por ejemplo; es:

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 necesitaré para especificar la pista (NOLOCK) en la unión para asegurar que no estoy cerrando la tabla unida?

Respuesta

116

No abordaré el argumento READ UNCOMMITTED, solo su pregunta original.

Sí, necesita WITH(NOLOCK) en cada tabla de la unión. No, tus consultas no son lo mismo.

Pruebe este ejercicio. Comience una transacción e inserte una fila en table1 y table2. No comprometer ni deshacer la transacción todavía.En este punto, su primera consulta será exitosa e incluirá las filas no confirmadas; su segunda consulta no regresará porque table2 no tiene la sugerencia WITH(NOLOCK).

+1

gracias por la respuesta concisa, justo lo que estaba buscando en este caso. – DanP

14

Estaba bastante seguro de que debe especificar el NOLOCK para cada JOIN en la consulta. Pero mi experiencia se limitó a SQL Server 2005.

Cuando busqué MSDN solo para confirmar, no pude encontrar nada definitivo. Las declaraciones de abajo parecen que me haga pensar, que para el año 2008, sus dos declaraciones anteriores son equivalentes, aunque para 2005 no es el caso:

[SQL Server 2008 R2]

de todos los seguros consejos se propagan a todas las tablas y vistas que son accedidas por el plan de consulta, incluidas las tablas y vistas a las que se hace referencia en una vista. Además, SQL Server realiza las comprobaciones de coherencia de bloqueo correspondientes.

[SQL Server 2005]

En SQL Server 2005, todas las sugerencias de bloqueo se propagan a todas las tablas y vistas que se hace referencia en una vista. Además, SQL Server realiza las comprobaciones de coherencia de bloqueo correspondientes.

Además, punto a destacar - y esto se aplica tanto a 2005 y 2008:

La tabla de consejos se ignoran si la tabla no se accede por el plan de consulta. Esto puede deberse a que el optimizador elige no acceder a la tabla, o porque se accede a una vista indexada. En este último caso, se puede evitar el acceso a una vista indexada utilizando la sugerencia de consulta OPTION (EXPAND VIEWS).

+0

@In Sane: Interesante ... gracias por eso ... Supongo que no estoy haciendo ningún daño al incluirlo en las UNIONES, incluso si no es del todo necesario. La documentación sobre NOLOCK es bastante escasa como usted ha mencionado; Tuve problemas para encontrar algo concluyente yo mismo. – DanP

+2

@InSane: ¿De dónde sacaste esta información? Parece ir en contra de la respuesta aceptada. –

+0

@notfed - remítase al enlace technet http://technet.microsoft.com/en-us/library/ms187373(v=sql.105).aspx - puede cambiar la versión de la base de datos en la parte superior para comparar el mismo artículo para diferentes versiones de el db – InSane

8

Ninguno. Establece el nivel de aislamiento en READ UNCOMMITTED que siempre es mejor que dar pistas de bloqueo individuales. O, mejor aún, si le interesan detalles como consistency, use snapshot isolation.

+0

@Remus: no estoy seguro de que pueda usar READ UNCOMMITTED en mi caso porque estoy accediendo a la conexión a través de NHibernate para realizar una llamada ADO.NET cruda especial; ¿se puede especificar esto en línea en la consulta, o obedecerá el nivel de transacción presente en la transacción de NHibernate? – DanP

+0

Envuelva la llamada en 'using (TransactionScope scope = new TransactionScope (..., TransactionOptions) {...}' y configure 'IsolationLevel' en las opciones: http://msdn.microsoft.com/en-us/ library/system.transactions.transactionoptions.isolationlevel.aspx –

+0

@Remus: Desafortunadamente, la gestión de transacciones se atiende en un nivel mucho más alto que este, así que tampoco es una opción. – DanP

Cuestiones relacionadas