Hay numerosas publicaciones de blog en este sitio relacionadas con las estadísticas de espera; son una de las métricas más importantes que puede usar al solucionar problemas de rendimiento en SQL Server. Las estadísticas de espera estuvieron disponibles en SQL Server 2005 y tradicionalmente han representado las esperas a nivel de instancia a través de sys.dm_os_wait_statistics. Esta información es excelente para solucionar problemas de rendimiento del sistema en general, pero al observar el rendimiento de las consultas, la información de espera solo se pudo ver cuando la consulta se estaba ejecutando y si estaba esperando un recurso a través de sys.dm_os_waiting_tasks. Los datos en sys.dm_os_waiting_tasks son transitorios (es lo que está esperando en este momento) y no es fácil de capturar y retener durante la vida de una consulta para ajustar el rendimiento en un momento posterior.
En SQL Server 2016, se expone un nuevo DMV, sys.dm_exec_session_wait_stats, que proporciona información sobre las esperas de una sesión activa existente. Si conoce el session_id, puede realizar un seguimiento de las esperas de una consulta cuando se inicia y cuando se completa (tome una instantánea de la información al principio y al final de la consulta y luego compare la información). El desafío es que debe conocer el session_id para la consulta y debe configurar la captura de datos por adelantado, lo cual no es trivial cuando se encuentra en medio de un problema de alta prioridad.
La información de estadísticas de espera existe en un plan de ejecución real que comienza en SQL Server 2016 SP1. Solo se capturan las 10 esperas principales y existen limitaciones en términos de lo que representan estos datos. Por ejemplo, CXPACKET se ignora y no se incluye en la salida, pero se incluirá en 2016 SP2 y 2017 CU3 y posteriores, donde CXCONSUMER captura las esperas de paralelismo irrelevantes (que no se incluirán en las esperas del plan real).
Entonces, ¿cómo podemos ver qué espera realmente una consulta específica? ¡Podemos usar Query Store! SQL Server 2017 incluye la captura de información de estadísticas de espera en Query Store, y esta funcionalidad también está disponible en Azure SQL Database. Las estadísticas de espera están vinculadas a un plan de consulta y se capturan a lo largo del tiempo, al igual que las estadísticas de tiempo de ejecución. La adición de información de estadísticas de espera en Query Store fue la solicitud de función número uno después de su lanzamiento inicial, y toda esa información en conjunto crea poderosas capacidades de resolución de problemas.
Cómo empezar
La captura de estadísticas de espera en Query Store está habilitada de forma predeterminada para Azure SQL Database. Cuando se crea una nueva base de datos en SQL Server 2017, o se actualiza una base de datos desde SQL Server 2014 o anterior, Query Store está deshabilitado de manera predeterminada... y, por lo tanto, la captura de estadísticas de espera está deshabilitada. Cuando una base de datos se actualiza desde SQL Server 2016, si tiene el Almacén de consultas habilitado, la recopilación de estadísticas de espera para el Almacén de consultas se habilitará tras la actualización.
Para fines de demostración, restauré la base de datos de WideWorldImporters, luego ejecuté las consultas a continuación para habilitar Query Store y borrar cualquier dato que pudiera haber existido previamente (solo es necesario porque esta es una base de datos de muestra):
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON; GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE ( OPERATION_MODE = READ_WRITE ); GO ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR; GO
La configuración predeterminada se usa con las declaraciones anteriores, y si desea modificar cualquiera de las opciones, puede hacerlo a través de la interfaz de usuario o mediante la declaración ALTER DATABASE. Ahora que Query Store está habilitado, comenzará a capturar datos de consulta, incluido el texto de la consulta, los planes, las estadísticas de tiempo de ejecución y las estadísticas de espera.
Mirando las estadísticas de espera
Para generar algunos datos, crearemos un procedimiento almacenado que ejecuta una consulta paralela repetidamente.
DROP PROCEDURE IF EXISTS [Sales].[OrderInfo]; GO CREATE PROCEDURE [Sales].[OrderInfo] AS BEGIN WHILE 1=1 BEGIN SELECT * FROM Sales.OrderLines ol INNER JOIN Warehouse.StockItems s ON ol.StockItemID = s.StockItemID OPTION (QUERYTRACEON 8649); END END
Luego, crea un archivo .cmd con el siguiente código:
start sqlcmd -S WIN2016\SQL2017 -d WideWorldImporters -q"EJECUTAR [Ventas].[InfoPedido];"salir
Esto nos permite no ejecute el SP dentro de Management Studio, lo que crea esperas ASYNC_NETWORK_IO significativas; queremos ver las esperas relacionadas con el paralelismo. Guarde el archivo .cmd, luego haga doble clic para ejecutar. Puede generar una carga adicional ejecutando varios archivos. Con este escenario veremos principalmente las esperas relacionadas con esta consulta, ya que no tenemos otra carga de trabajo. No dude en ejecutar otras consultas en la base de datos de WideWorldImporters al mismo tiempo si desea generar aún más datos de espera.
Después de varios minutos, detenga los archivos de comando y expanda la base de datos de WideWorldImporters dentro de Management Studio para ver la carpeta Query Store y los informes debajo. Si abre el informe Consultas de mayor consumo de recursos, debería ver la consulta del procedimiento almacenado como la consulta principal.
La vista predeterminada de este informe muestra las consultas con la duración total más alta. Para ver consultas basadas en estadísticas de espera, podemos seleccionar el botón Configurar y cambiarlo a Tiempo de espera (ms).
Botón Configurar en la vista de informe (arriba a la derecha) Cambiar el recurso del informe Tenga en cuenta que también puede configurar el intervalo de tiempo y el número de consultas devueltas. Para este ejemplo, la última hora es aceptable.Si pasa el cursor sobre la barra de la primera consulta, puede ver los tiempos de espera para la consulta. Esta vista es actualmente la única forma de ver la información de espera en la interfaz de usuario, pero se espera que aparezcan informes adicionales específicos para las estadísticas de espera en una versión futura de Management Studio.
Información de espera en la interfaz de usuario
Aquellos de ustedes que han trabajado con estadísticas de espera por un tiempo notarán que las descripciones del tipo de espera son diferentes. Es decir, en lugar de un tipo de espera CXPACKET para indicar el paralelismo, simplemente verá "Tipo de espera de paralelismo". Esta es una diferencia fundamental en Query Store:los tipos de espera se agrupan en categorías. Hay más de 900 tipos de espera diferentes en SQL Server en este momento, y tratar de rastrear cada uno por separado es extremadamente costoso. Además, el Almacén de consultas se diseñó pensando en todos los profesionales de datos:ya sea que sea un experto en el ajuste del rendimiento o que recién esté comenzando a comprender cómo funciona SQL Server, debería poder utilizar el Almacén de consultas para encontrar fácilmente las consultas de bajo rendimiento. Eso también significa hacer que la información de espera sea más fácil de entender. Para obtener una lista completa de las categorías de espera y los tipos de espera dentro, visite la documentación de sys.query_store_wait_stats.
También puede ver la información de espera mediante T-SQL. Una consulta de ejemplo es la siguiente, que incluye la consulta, los plan_id(s) para esa consulta y las estadísticas de espera para un intervalo de tiempo determinado:
SELECT TOP (10) [ws].[wait_category_desc], [ws].[avg_query_wait_time_ms], [ws].[total_query_wait_time_ms], [ws].[plan_id], [qt].[query_sql_text], [rsi].[start_time], [rsi].[end_time] FROM [sys].[query_store_query_text] [qt] JOIN [sys].[query_store_query] [q] ON [qt].[query_text_id] = [q].[query_text_id] JOIN [sys].[query_store_plan] [qp] ON [q].[query_id] = [qp].[query_id] JOIN [sys].[query_store_runtime_stats] [rs] ON [qp].[plan_id] = [rs].[plan_id] JOIN [sys].[query_store_runtime_stats_interval] [rsi] ON [rs].[runtime_stats_interval_id] = [rsi].[runtime_stats_interval_id] JOIN [sys].[query_store_wait_stats] [ws] ON [ws].[runtime_stats_interval_id] = [rs].[runtime_stats_interval_id] AND [ws].[plan_id] = [qp].[plan_id] WHERE [rsi].[end_time] > DATEADD(MINUTE, -5, GETUTCDATE()) AND [ws].[execution_type] = 0 ORDER BY [ws].[avg_query_wait_time_ms] DESC;
Resultado de consulta
Si bien ahora puede ver todas las esperas para una consulta determinada y su plan, aún tendrá que profundizar en el rendimiento para comprender, por ejemplo, por qué una consulta se ejecuta en paralelo (cuando tal vez no lo desee) o lo que podría estar bloqueando una consulta. Tenga en cuenta que las estadísticas de espera, al igual que las estadísticas de tiempo de ejecución, están vinculadas al plan de consulta a lo largo del tiempo. En este resultado, la duración del intervalo para Query Store se establece en 10 minutos, por lo que las estadísticas de espera son para cada plan para ese intervalo de 10 minutos (11:50 p. m. del 21 de noviembre de 2017 a la medianoche del 22 de noviembre de 2017). De forma predeterminada, la duración del intervalo cuando habilita Query Store es de 60 minutos.
Resumen
Las estadísticas de espera, combinadas con los planes de consultas individuales, hacen de Query Store una herramienta aún más formidable para solucionar problemas de rendimiento del sistema y de consultas. Query Store es la única función que le permite capturar de forma nativa consultas, planes, métricas de rendimiento y estadísticas de espera, todo en una sola ubicación. Para aquellos de ustedes que están acostumbrados a la gran cantidad de tipos de espera, el ajuste a las categorías utilizadas en Query Store debería ser sencillo. Para cualquiera que sea nuevo en las estadísticas de espera, las categorías son un excelente lugar para comenzar a comprender el recurso que está esperando una consulta.