Una consulta como la siguiente que está garantizada para no devolver ninguna fila, toma de 0 a 160 segundos en uno de nuestros servidores:
select col1, col2, col3
from tab1
where 0 = 1
Hace dos semanas, esto sucedió seis veces en un intervalo de 48 horas. La semana pasada la misma consulta tomó ~ 0 segundos. Tengo registros de los SQL de nuestra aplicación, pero todavía no he encontrado ningún sospechoso. Además, pensé que una consulta de tipo 0 / donde 0 = 1 nunca llegaba a las páginas de datos, por lo que debería ser resistente a los bloqueos de datos de fila / página / tabla. El esquema no es tocado por ningún SQL (conocido).
Dado que el problema no es consistente, y el servidor está bajo una carga muy pesada, me gustaría entender la teoría detrás de lo que está sucediendo antes de conectar el generador de perfiles SQL. Otras consultas se ejecutan sin problemas durante estos retrasos. Un problema conocido en la aplicación es una gran cantidad de consultas SQL creadas dinámicamente: alrededor de 200k consultas únicas de 850k consultas totales (registradas) durante un período de 48 horas, ¿puede esto causar problemas como este?
El servidor ejecuta la edición estándar de SQL Server 2005, 96 GB de RAM, discos en SAN y 4 CPU / 16 núcleos. Los archivos de base de datos y los grupos de archivos están bien optimizados y no deberían ser un problema (pero estamos analizando esto por separado).
Cualquier puntero donde mirar es muy apreciado.
Editar: ¡Perfecto! Reproduje la consulta para agregar el plan de ejecución, y tardó 1 minuto y 35 segundos. Aquí está el plan de ejecución y la captura de pantalla que muestra la duración de la consulta:
Edición 2: detalles de tiempo de estadísticas para una segunda ejecución. Parece ser constantemente lento en este momento, por lo que adjuntaremos profiler y perfmon:
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 97402 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
fuente
Respuestas:
Parece que incluso con una
... WHERE 0 = 1
cláusula que todavía habrá un requisito para unIS
bloqueo de intención compartida ( ) en la tabla. Probemos esto:Comenzaré creando una tabla de prueba:
Ahora que tengo mi tabla de prueba, en una sesión (ventana de consulta) voy a ejecutar lo siguiente para poner un
X
bloqueo exclusivo ( )dbo.MyTestTable1
:Puedo verificar el bloqueo exclusivo mirando el
sys.dm_tran_locks
DMV. Luego, en otra sesión (nueva ventana de consulta) hago exactamente lo que hace su consulta:A primera vista veo que no se está completando. Mirando
sys.dm_exec_requests
, veo exactamente por qué este es el caso:Puedo ver aquí que mi
... WHERE 0 = 1
consulta está esperando unIS
bloqueo para este objeto (que object_id se traduce adbo.MyTestTable1
).De ninguna manera estoy diciendo que la concurrencia es su problema, pero por lo que parece, está exhibiendo los síntomas. El ejemplo anterior es para demostrar que no está exento de bloquear y bloquear incluso con una
WHERE
cláusula que nunca devolverá datos.Todo lo que podemos hacer es adivinar, por lo que lo que debe hacer cuando está "tomando mucho tiempo" es ver exactamente qué está haciendo esa solicitud que está tomando tanto tiempo. Si está esperando algo, entonces mira lo que está esperando.
fuente
Dependiendo de cuán puntiagudos e hilos requieran sus consultas, su sistema podría simplemente poner en cola esa consulta. El recuento de trabajadores predeterminado (es decir, el número de subprocesos simultáneos del servidor SQL) para su configuración debe ser de aproximadamente 700.
Consulte sys.dm_os_schedulers y sys.dm_os_waiting_tasks para ver si eso podría ser un problema.
fuente