2012-06-08 9 views
9

Actualmente estoy ejecutando la siguiente instrucción¿Qué está bloqueando "Seleccione top 1 * from TableName with (nolock)" para devolver un resultado?

select * into adhoc..san_savedi from dps_san..savedi_record 

Se trata de tomar una dolorosamente mucho tiempo y me gustaría ver qué tan avanzado es así que corrí esto:

select count(*) from adhoc..san_savedi with (nolock) 

Ese didn' t devuelve nada en el momento oportuno por lo que para el gusto de hacerlo lo hice:

select top 1 * from adhoc..san_savedi with (nolock) 

Aun que parece funcionar indefinidamente. Podría entender si hay millones de registros que el recuento (*) podría llevar mucho tiempo, pero no entiendo por qué seleccionar el registro de la parte superior 1 no volvería casi inmediatamente, considerando que especifique nolock.

En nombre de la divulgación completa, dps_san es una vista que extrae de una conexión odbc a través del servidor vinculado. No creo que eso afecte el por qué no puedo regresar a la fila superior, sino simplemente tirarlo por si me equivoco.

Entonces, ¿quiero saber qué es lo que impide que esta declaración se ejecute?

EDIT:

Como he mencionado anteriormente, sí dps_san..savedi_record es una vista. Esto es lo que hace:

select * from DPS_SAN..root.SAVEDI_RECORD 

No es nada más que un alias y no hace ninguna agrupación/clasificación/etc así que no creo que el problema radica aquí, pero por favor aclararme si estoy equivocado.

+3

¿Qué hace la vista? Si realiza BYBs grupales, ORDER BYs o usa funciones agregadas, entonces podría ser que seleccionar la fila superior 1 sea casi tan costoso como seleccionarlos a todos. –

+0

¿Estás seguro de que SELECT INTO ya ha escrito una sola fila en el disco? Tal vez todavía esté en modo de bloqueo de esquema porque todavía está esperando que ODBC entregue la primera fila desde su conexión vinculada. –

+0

@ Aaronofertrand No, no estoy seguro. Sin embargo, puedo abrir otra ventana de consulta y seleccionar registros de dps_san..savedi_record todo lo que quiero y obtener resultados, por lo que sería extraño si no hubiera escrito ningún resultado hasta ahora (han sido más de 2 horas). –

Respuesta

11

SELECT consultas con NOLOCK en realidad no tomar ninguna cerradura, todavía necesitan una cerradura SCH-S (estabilidad esquema) sobre la mesa (and as it is a heap it will also take a hobt lock).

Además, antes de que el SELECT incluso pueda comenzar SQL Server debe compilar un plan para la instrucción, que también requiere que tome un bloqueo SCH-S en la tabla.

Como su transacción de larga ejecución crea la tabla a través de SELECT ... INTO, tiene un bloqueo SCH-M incompatible hasta que finalice la instrucción.

Usted puede verificar esto buscando en sys.dm_os_waiting_tasks mientras mientras durante el período de bloqueo.

cuando intenté lo siguiente en una conexión

BEGIN TRAN 

SELECT * 
INTO NewT 
FROM master..spt_values 

/*Remember to rollback/commit this later*/ 

Y luego ejecutar (o simplemente tratando de ver el plan de ejecución estimado)

SELECT * 
FROM NewT 
WITH (NOLOCK) 

en un segundo la consulta de lectura fue bloqueado.

SELECT wait_type, 
     resource_description 
FROM sys.dm_os_waiting_tasks 
WHERE session_id = <spid_of_waiting_task> 

Muestra el tipo de espera es de hecho SCH_S y el recurso de bloqueo SCH-M

wait_type  resource_description 
---------------- ------------------------------------------------------------------------------------------------------------------------------- 
LCK_M_SCH_S  objectlock lockPartition=0 objid=461960722 subresource=FULL dbid=1 id=lock4a8a540 mode=Sch-M associatedObjectId=461960722 
+1

+1 pero casi no lo hice por "while" :-) –

+0

@ AaronBertrand - Gracias, piense "mientras" está bien que los británicos lo usen [según Wikipedia] (http://en.wikipedia.org/wiki/ Mientras)! –

+0

Eso no significa que deba gustarme. Los británicos también pueden usar "while" ¿no? :-) –

2

Es muy posible que no haya bloqueos ... Si dps_san..savedi_record es una vista, puede llevar mucho tiempo ejecutarla, ya que puede estar accediendo a tablas sin usar un índice, o puede estar ordenando millones de registros, o cualquier otra razón. Entonces su consulta, incluso un simple top o conteo, será solo tan rápido como se pueda ejecutar esa vista.

+0

El select está contra una tabla que se está poblando, no una vista. –

+0

Ver mi edición. La vista solo selecciona *. Sin agrupar/clasificar/ni nada que pueda hacer que necesite escanear toda la tabla antes de devolver resultados o algo por el estilo. –

+0

@AaronBertrand Me imaginé que estaba diciendo lo mismo que sugirió, que puede que aún no haya logrado insertar ningún registro. –

2

Algunos problemas a considerar aquí. ¿Es dps_san..savedi_record una vista? Si es así, podría tomar mucho tiempo obtener sus datos. La otra cosa que puedo pensar es que estás tratando de crear una tabla temporal usando la sintaxis select into, lo cual es una mala idea. La sintaxis select * into ... bloqueará el tempdb durante la duración de la selección.

Si está creando la tabla con esa sintaxis, existe una solución alternativa. En primer lugar, crear la tabla lanzando where 1=0 al final de su declaración inicial:

select * into ... from ... where 1=0 

Esto creará la tabla primero (que es rápido), que le permite a insert into porque la tabla existe ahora (sin penalización del tempdb bloqueo para la duración de la consulta).

+0

@ AaronBertrand Usted está en lo correcto señor, gracias por arreglar eso para mí (se olvidó de que solo se puede usar para crear una tabla). [Seleccione en ... Referencia] (http://msdn.microsoft.com/en-us/library/ms190750 (v = sql.105) .aspx) – SPFiredrake

+0

Gracias, le daré una oportunidad. –

2

Encuentra la session_id que está realizando la select into:

SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time 
    FROM sys.dm_exec_requests AS r 
    CROSS APPLY sys.dm_exec_sql_text(r.plan_handle) AS t 
    WHERE t.[text] LIKE '%select%into%adhoc..san_savedi%'; 

Esto debería saber si otra sesión está bloqueando la selección en o si tiene un tipo de espera que está causando un problema.

Puede repetir el proceso en otra ventana para la sesión que está intentando hacer la selección. Sospecho que Martin tiene razón y que mi comentario anterior sobre el bloqueo del esquema es relevante.

+0

s son r's, supongo. –

+0

@BrandonMoore sí –

Cuestiones relacionadas