Ci sono numerosi post di blog su questo sito relativi alle statistiche di attesa; sono una delle metriche più importanti che puoi utilizzare durante la risoluzione dei problemi di prestazioni in SQL Server. Le statistiche di attesa sono state rese disponibili in SQL Server 2005 e tradizionalmente hanno rappresentato le attese a livello di istanza tramite sys.dm_os_wait_statistics. Queste informazioni sono ottime durante la risoluzione dei problemi delle prestazioni del sistema in generale, ma quando si esaminano le prestazioni della query, le informazioni sull'attesa possono essere visualizzate solo quando la query era in esecuzione e se era in attesa su una risorsa tramite sys.dm_os_waiting_tasks. I dati in sys.dm_os_waiting_tasks sono temporanei (è ciò che è in attesa in questo momento) e non è facile acquisire e conservare per tutta la durata di una query per l'ottimizzazione delle prestazioni in un secondo momento.
In SQL Server 2016 viene esposto un nuovo DMV, sys.dm_exec_session_wait_stats, che fornisce informazioni sulle attese per una sessione attiva esistente. Se conosci session_id, puoi tenere traccia delle attese di una query all'avvio e al completamento (fotografare le informazioni all'inizio e alla fine della query e quindi differenziare le informazioni). La sfida è che devi conoscere il session_id per la query e devi impostare l'acquisizione dei dati in anticipo, il che non è banale quando sei nel mezzo di un problema ad alta priorità.
Le informazioni sulle statistiche di attesa esistono in un piano di esecuzione effettivo a partire da SQL Server 2016 SP1. Vengono acquisite solo le prime 10 attese e ci sono limitazioni in termini di ciò che questi dati rappresentano. Ad esempio, CXPACKET viene ignorato e non incluso nell'output, ma verrà incluso in SP2 2016 e CU3 2017 e versioni successive, dove le attese di parallelismo irrilevanti vengono invece catturate da CXCONSUMER (che non sarà incluso nelle attese del piano effettive).
Quindi, come possiamo vedere cosa sta veramente aspettando una query specifica? Possiamo usare Query Store! SQL Server 2017 include l'acquisizione delle informazioni sulle statistiche di attesa in Query Store e questa funzionalità è disponibile anche nel database SQL di Azure. Le statistiche di attesa sono legate a un piano di query e vengono acquisite nel tempo, proprio come le statistiche di runtime. L'aggiunta di informazioni sulle statistiche di attesa in Query Store è stata la richiesta di funzionalità numero uno dopo il suo rilascio iniziale e tutte queste informazioni insieme creano potenti funzionalità di risoluzione dei problemi.
Per iniziare
L'acquisizione delle statistiche di attesa in Query Store è abilitata per impostazione predefinita per il database SQL di Azure. Quando viene creato un nuovo database in SQL Server 2017 o un database viene aggiornato da SQL Server 2014 o versioni precedenti, Query Store è disabilitato per impostazione predefinita... e quindi l'acquisizione delle statistiche di attesa è disabilitata. Quando un database viene aggiornato da SQL Server 2016, se ha Query Store abilitato, la raccolta delle statistiche di attesa per Query Store verrà abilitata al momento dell'aggiornamento.
A scopo dimostrativo, ho ripristinato il database WideWorldImporters, quindi ho eseguito le query seguenti per abilitare Query Store e cancellare tutti i dati che potrebbero essere esistiti in precedenza (necessario solo perché questo è un database di esempio):
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
Le impostazioni predefinite vengono utilizzate con le istruzioni precedenti e, se si desidera modificare una qualsiasi delle opzioni, è possibile farlo tramite l'interfaccia utente o tramite l'istruzione ALTER DATABASE. Ora che Query Store è abilitato, inizierà ad acquisire i dati della query, inclusi il testo della query, i piani, le statistiche di runtime e le statistiche di attesa.
Guardando le statistiche di attesa
Per generare alcuni dati, creeremo una procedura memorizzata che esegue ripetutamente una query parallela.
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
Quindi, crea un file .cmd con il codice seguente:
start sqlcmd -S WIN2016\SQL2017 -d WideWorldImporters -q"EXECUTE [Sales].[OrderInfo];"exit
Questo ci consente di non eseguire l'SP all'interno di Management Studio, che crea attese ASYNC_NETWORK_IO significative; vogliamo vedere le attese legate al parallelismo. Salva il file .cmd, quindi fai doppio clic per eseguire. È possibile generare un carico aggiuntivo eseguendo più file. Con questo scenario vedremo principalmente le attese relative a questa query, poiché non abbiamo altro carico di lavoro. Sentiti libero di eseguire altre query sul database WideWorldImporters contemporaneamente se desideri generare ancora più dati di attesa.
Dopo alcuni minuti, interrompere i file di comando ed espandere il database WideWorldImporters in Management Studio per visualizzare la cartella Query Store e i report sottostanti. Se apri il rapporto Query che consumano più risorse, dovresti vedere la query della stored procedure come la query principale.
La visualizzazione predefinita per questo rapporto mostra le query con la durata totale più elevata. Per visualizzare le query basate sulle statistiche di attesa, possiamo selezionare il pulsante Configura e cambiarlo in Tempo di attesa (ms).
Configura pulsante nella visualizzazione rapporto (in alto a destra) Modifica della risorsa per il rapporto Tieni presente che puoi anche configurare l'intervallo di tempo e il numero di query restituite. Per questo esempio, l'ultima ora è accettabile.Se passi il mouse sopra la barra per la prima query, puoi vedere i tempi di attesa per la query. Questa visualizzazione è attualmente l'unico modo per visualizzare le informazioni sull'attesa nell'interfaccia utente, ma si spera che in una versione futura di Management Studio arriveranno rapporti aggiuntivi specifici per le statistiche di attesa.
Attendere le informazioni nell'interfaccia utente
Quelli di voi che hanno lavorato con le statistiche di attesa per un po' noteranno che le descrizioni del tipo di attesa sono diverse. Cioè, invece di un tipo di attesa CXPACKET per indicare il parallelismo, vedi semplicemente "Tipo di attesa di parallelismo". Questa è una differenza fondamentale in Query Store:i tipi di attesa sono raggruppati in categorie. Esistono oltre 900 diversi tipi di attesa in SQL Server a questo punto e il tentativo di tenerne traccia separatamente è estremamente costoso. Inoltre, Query Store è stato progettato pensando a tutti i professionisti dei dati:che tu sia un esperto di ottimizzazione delle prestazioni o che tu abbia appena iniziato a comprendere come funziona SQL Server, dovresti essere in grado di utilizzare Query Store per trovare facilmente query con prestazioni scadenti. Ciò significa anche semplificare la comprensione delle informazioni sull'attesa. Per un elenco completo delle categorie di attesa e dei tipi di attesa all'interno, visita la documentazione per sys.query_store_wait_stats.
Puoi anche visualizzare le informazioni sull'attesa usando T-SQL. Una query di esempio è quella seguente, che include la query, i plan_id per quella query e le statistiche di attesa per un determinato intervallo di tempo:
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;
Risultato della query
Anche se ora puoi vedere tutte le attese per una determinata query e il suo piano, dovrai comunque approfondire le prestazioni per capire, ad esempio, perché una query viene eseguita in parallelo (quando forse non lo desideri) o cosa potrebbe bloccare una query. Si noti che le statistiche di attesa, proprio come le statistiche di runtime, sono legate al piano di query nel tempo. In questo output, la durata dell'intervallo per Query Store è impostata su 10 minuti, quindi le statistiche di attesa si riferiscono a ciascun piano per quell'intervallo di 10 minuti (dalle 23:50 del 21 novembre 2017 alla mezzanotte del 22 novembre 2017). Per impostazione predefinita, la durata dell'intervallo quando si abilita Query Store è di 60 minuti.
Riepilogo
Le statistiche di attesa, combinate con i singoli piani di query, rendono Query Store uno strumento ancora più formidabile per la risoluzione dei problemi delle prestazioni del sistema e delle query. Query Store è l'unica funzionalità che consente di acquisire in modo nativo query, pianificazione, metriche delle prestazioni e statistiche di attesa in un'unica posizione. Per quelli di voi abituati alla miriade di tipi di attesa, l'adeguamento alle categorie utilizzate in Query Store dovrebbe essere semplice. Per chi non conosce le statistiche di attesa, le categorie sono un ottimo punto di partenza per comprendere la risorsa per la quale è in attesa una query.