SQL Server 2014 Retraso repentino / Sin inserciones / No relacionado con hardware o índice

8

Estoy ejecutando una 350GBbase de datos en mi PC con ~ 40 millones de filas.

SQL Server 2014, Win7, AMD 8350 @ 4.8GHZ, 16 GB de RAM y un SSD de 500 GB (la base de datos está alojada en su propio SSD de 500 GB, con un rendimiento de lectura / escritura de 500MB / 500MB).

La base de datos no se está actualizando, solo la estoy analizando / leyendo. Con la creación de unos pocos indexes, cualquiera join, count(*)etc., toma menos de 1 minuto, lo cual está bien para mis propósitos. He estado ejecutando algunas consultas (después de ejecutar una sola consulta de combinación, 40-50 veces, se vuelve lenta) en los datos, y ahora las llamadas que tomaron 1 minuto, todavía se ejecutan 20 minutos más tarde.

Mantengo un ojo cuidadoso en los recursos del sistema, y ​​puedo ver el efecto SSDcuando comienza la consulta, se lee durante 20-30 segundos, luego se lee en 121kB/secondlos próximos 20 minutos. Esto no es un problema de CPU o problema de disco. Estoy limitado con mi cantidad de RAM, sin embargo, las llamadas funcionan bien cuando cargué la base de datos por primera vez, ahora, nada se ejecuta, 25 minutos después.

Efectivamente, ya no puedo consultar la base de datos, cualquier llamada lleva demasiado tiempo, incluso una SELECTdeclaración básica . He intentado reconstruir los índices y actualizar las estadísticas, pero no hay diferencia.

No tengo mucha experiencia en esto, por lo que es muy posible que mi consulta SQL sea incorrecta, en cuyo caso esperaría un error o que termine de ejecutarse con 0 resultados, pero ninguno de los dos ocurre.

Lo que estoy tratando de hacer es contar todas las instancias de un 'TypeID', en los 5 segundos anteriores a un tiempo basado en la tabla ACALLS.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

Después de ejecutar "Who is Running", ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí


fuente
Sospecho que esto tiene que ver con las estadísticas en las tablas y los tipos de procesamiento realizados para las uniones. Debe mirar los planes de ejecución de las consultas: las uniones de bucle anidado pueden ser un signo de problemas.
Gordon Linoff
¿Has probado CON RECOMPILE?
3
Publique un plan de ejecución real de una consulta sorprendentemente lenta. Cuanto más simple sea la consulta, mejor.
usr
1
¿Has actualizado las estadísticas de todas las tablas? ¿Has reconstruido todos los índices? Información sobre sp_whoisactive: enlace
TT.
2
Esas estadísticas de espera muestran una gran cantidad de IO, pero no sabemos qué proporción de la consulta es IO y qué es la CPU. Realice las pruebas que recomendé como publicar los resultados.
usr

Respuestas:

2

Tiene una consulta no SARGable, incluso si tiene buenos índices, no los está usando con esa consulta.

Primero, una reacción instintiva a pageiolatch_sh es leer páginas del disco en el búfer; no tienes suficiente RAM para los datos que intenta extraer.

En segundo lugar, debe analizar el plan de ejecución y su uso de índices, o su falta.

Deje de usar funciones en sus uniones y su DÓNDE, y solo obtenga los datos con los que absolutamente necesita comenzar.

  • "ENTRE ACALLS. StartTime y DATEADD (ss, -5, ACALLS.StartTime)" - deshazte de ese DATEADD en ENTRE.

    • Si se trata de una base de datos de informes de solo lectura, cree una tabla de informes con solo los datos que necesita y luego coloque índices compuestos según sea necesario. Use esa para obtener las claves primarias / otras claves únicas de las filas ACALLS que necesita, luego obtenga el resto de los datos ACALLS más adelante.
  • WHERE DATEPART (hora, MainView.TimeStamp) ENTRE 10 y 13 y CAST (MainView.TimeStamp como fecha) = '2015-12-09'

    • lo mismo: deshacerse de CAST: cambiar '2015-12-09' a uno o dos parámetros del tipo de datos correcto para MainView.TimeStamp> = @StartTimestamp AND MainView.TimeStamp <@EndTimestamp

    • y deshacerse de ese DATEPART restringiendo @StartTimestamp y @EndTimestamp para incluir también los criterios de horas.

Quizás cargue una tabla #temp con solo las claves primarias / únicas de las filas que cumplen con los criterios de MainView antes de la unión.

Hmm ... también, si Mainview es una vista compleja, vaya directamente a las tablas base para cargar esa tabla #temp

No olvide usar Profiler para verificar y ver si agregar índices (compuestos si es necesario) en el #temp u otra tabla de etapas es una ganancia neta o una pérdida neta :).

Contraseñas anti-débiles
fuente
1

crear un índice compuesto no agrupado en mainview (typeid, timestamp).

cambie su "dónde" en la vista principal para que no esté usando una función contra las columnas de la vista principal. esto puede requerir que precalcule estos valores como variables antes de ejecutar la consulta si necesita que sean más dinámicos.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

cree un índice no agrupado en ACALLS.StartTime.

cambie la unión a ACALLS para que sea

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

Según tengo entendido, eso manejará su lógica y se unirá a un rendimiento bastante alto y lo alejará del IO.

mi mejor conjetura en cuanto a lo que está encontrando es que sus datos se están vaciando de la caché y / o tempdb se está derramando en el disco de vez en cuando, por lo que la mejor solución que he encontrado es escribir las consultas mejor solo limite el uso de memoria y tempdb y los problemas subyacentes desaparecen.

Bruce Dunwiddie
fuente