Condividi tramite


Tipo di agente di raccolta Attività query

Il tipo di agente di raccolta Attviità query è un tipo di agente personalizzato utilizzato dal set di raccolta Statistiche query, uno dei set di raccolta dati di sistema predefiniti.

Questo tipo di agente di raccolta viene utilizzato per raccogliere statistiche e informazioni sulle attività relative alle query con il piano e il testo delle query che soddisfano criteri predefiniti. Se si crea un set di raccolta personalizzato con questo tipo di agente di raccolta, verranno raccolte le stesse informazioni ottenute con il set di raccolta Statistiche query. Pertanto, si consiglia di utilizzare il set di raccolta Statistiche query predefinito.

Architettura ed elaborazione

Il tipo di agente di raccolta Attività query è costituito dagli elementi seguenti:

  • Uno schema dei parametri di input (interno)

  • Un pacchetto SSIS per la raccolta di dati (QueryActivityCollect.dtsx)

  • Un pacchetto SSIS per il caricamento di dati (QueryActivityUpload.dtsx)

Questo tipo di agente di raccolta utilizza inoltre attività o trasformazioni personalizzate per analizzare e selezionare dati per l'archiviazione nel data warehouse di gestione.

Il tipo di agente di raccolta Attività query effettua le operazioni seguenti:

  • Raccolta di esempi dm_exec_requests, dm_exec_sessions e selezione delle altre viste a gestione dinamica correlate. Questa attività viene implementata come singola query unita in join. La raccolta dati si verifica con la frequenza specificata per l'elemento della raccolta.

  • Raccolta di snapshot della vista a gestione dinamica dm_exec_query_stats con una frequenza uguale a quella di caricamento del set di raccolta. Per impostazione predefinita, la frequenza di caricamento del set di raccolta Statistiche query è di 15 minuti.

Fase di raccolta

Nella tabella seguente viene illustrata la query utilizzata durante la fase di raccolta. Tale query è definita nel pacchetto SSIS QueryActivityCollect.dtsx.

Frequenza di raccolta

10 secondi

Query

SET NOCOUNT ON
-- Get the collection time as UTC time
DECLARE @collection_time datetime
SET @collection_time = GETDATE()
SELECT
CONVERT(int, ROW_NUMBER() OVER (ORDER BY sess.session_id, ISNULL (req.request_id, -1), ISNULL (tasks.exec_context_id, -1)) ) AS row_id,
-- IDs and Blocking IDs
sess.session_id, 
ISNULL (req.request_id, -1) AS request_id, 
ISNULL (tasks.exec_context_id, -1) AS exec_context_id, 
ISNULL (req.blocking_session_id, 0) AS blocking_session_id,
CONVERT (bit, CASE 
                WHEN EXISTS (SELECT TOP 1 session_id FROM sys.dm_exec_requests bl WHERE bl.blocking_session_id = req.session_id) THEN 1
                ELSE 0
              END) AS is_blocking,
ISNULL (waits.blocking_exec_context_id, 0) AS blocking_exec_context_id, 
tasks.scheduler_id, 
DB_NAME(req.database_id) as database_name, 
req.[user_id], 
-- State information
LEFT (tasks.task_state, 10) AS task_state, 
LEFT (req.status, 15) AS request_status, 
LEFT (sess.status, 15) AS session_status,
req.executing_managed_code, 
-- Session information
sess.login_time, 
sess.is_user_process, 
LEFT (ISNULL (sess.[host_name], ''), 20) AS [host_name], 
LEFT (ISNULL (sess.[program_name], ''), 50) AS [program_name], 
LEFT (ISNULL (sess.login_name, ''), 30) AS login_name, 
-- Waits information
LEFT (ISNULL (req.wait_type, ''), 45) AS wait_type, 
LEFT (ISNULL (req.last_wait_type, ''), 45) AS last_wait_type, 
ISNULL (waits.wait_duration_ms, 0) AS wait_duration_ms, 
LEFT (ISNULL (req.wait_resource, ''), 50) AS wait_resource, 
LEFT (ISNULL (waits.resource_description, ''), 140) AS resource_description,
-- Transaction information
req.transaction_id, 
ISNULL(req.open_transaction_count, 0) AS open_transaction_count,
COALESCE(req.transaction_isolation_level, sess.transaction_isolation_level) AS transaction_isolation_level,
-- Request stats
req.cpu_time AS request_cpu_time, 
req.logical_reads AS request_logical_reads, 
req.reads AS request_reads, 
req.writes AS request_writes, 
req.total_elapsed_time AS request_total_elapsed_time, 
req.start_time AS request_start_time, 
-- Session stats
sess.memory_usage, 
sess.cpu_time AS session_cpu_time, 
sess.reads AS session_reads, 
sess.writes AS session_writes, 
sess.logical_reads AS session_logical_reads, 
sess.total_scheduled_time AS session_total_scheduled_time, 
sess.total_elapsed_time AS session_total_elapsed_time, 
sess.last_request_start_time, 
sess.last_request_end_time, 
req.open_resultset_count AS open_resultsets, 
sess.row_count AS session_row_count, 
sess.prev_error, 
tasks.pending_io_count, 
-- Text/Plan handles
ISNULL (req.command, 'AWAITING COMMAND') AS command,  
req.plan_handle, 
req.sql_handle, 
req.statement_start_offset, 
req.statement_end_offset,
@collection_time AS collection_time
FROM sys.dm_exec_sessions sess 
LEFT OUTER MERGE JOIN sys.dm_exec_requests req  ON sess.session_id = req.session_id
LEFT OUTER MERGE JOIN sys.dm_os_tasks tasks ON tasks.session_id = sess.session_id AND tasks.request_id = req.request_id AND tasks.task_address = req.task_address
LEFT OUTER MERGE JOIN sys.dm_os_waiting_tasks waits ON waits.session_id = sess.session_id AND waits.waiting_task_address = req.task_address
WHERE 
    sess.session_id <> @@SPID
    AND
    (
        (req.session_id IS NOT NULL AND (sess.is_user_process = 1 OR req.status COLLATE Latin1_General_BIN NOT IN ('background', 'sleeping')))-- active request
            OR 
        (sess.session_id IN (SELECT DISTINCT blocking_session_id FROM sys.dm_exec_requests WHERE blocking_session_id != 0))            -- not active, but head blocker
    )
OPTION (FORCE ORDER)

Fase di caricamento

Durante la fase di caricamento i dati raccolti vengono analizzati per determinare quali verranno salvati nel data warehouse di gestione. Questa analisi determina un set di statistiche della query nonché piani e testo della query che è necessario salvare.

Un elemento fondamentale è un algoritmo che seleziona le query e i piani di query da salvare nel data warehouse. Le operazioni dell'algoritmo sono le seguenti:

  1. Raccolta di uno snapshot di sys.dm_exec_query_stats. Questo snapshot viene raccolto a una frequenza uguale a quella di caricamento del set di raccolta. Il valore predefinito è 15 minuti.

  2. Recupero dello snapshot più recente (eseguito fino a 15 minuti prima) per confrontarlo con quello nuovo. Lo snapshot più recente è memorizzato nella cache localmente e non occorre che sia recuperato dal data warehouse di gestione.

  3. Selezione delle prime tre query da ogni snapshot tramite le metriche seguenti:

    • Tempo trascorso

    • Tempo di lavoro

    • Letture logiche

    • Scritture logiche

    • Letture fisiche

    • Conteggio esecuzioni

    Questo processo fornisce 6 x 3 sql_handles e plan_handles.

  4. Identificazione degli sql_handles e plan_handles univoci.

  5. Intersezione di questo risultato con gli sql_handles e plan_handles archiviati nel data warehouse.

    Per nuovi sql_handles e plan_handles, acquisizione del piano e del testo dal server. Se non è possibile trovare il piano o il testo (potrebbe essere già stato rimosso dalla cache locale), archiviazione degli handle nel data warehouse di gestione.

  6. Per ogni testo dello sql_handle raccolto, normalizzazione del testo (ad esempio, rimozione di parametri e valori letterali) e calcolo del valore hash univoco per il testo normalizzato. Archiviazione del testo normalizzato, del valore hash e del mapping all'sql_handle originale nel data warehouse di gestione.

Nella tabella seguente viene illustrata la query utilizzata per ottenere gli snapshot, nonché per analizzare e quindi caricare i dati nel data warehouse di gestione. Tale query è definita nel pacchetto SSIS QueryActivityUpload.dtsx.

Query

SET NOCOUNT ON
DECLARE @p1 datetime
SET @p1 = GETDATE()
SELECT 
    [sql_handle],
    statement_start_offset,
    statement_end_offset,
    -- Use ISNULL here and in other columns to handle in-progress queries that are not yet in sys.dm_exec_query_stats.  
    -- These values only come from sys.dm_exec_query_stats. If the plan does not show up in sys.dm_exec_query_stats 
    -- (first execution of a still-in-progress query, visible in sys.dm_exec_requests), these values will be NULL. 
    MAX (plan_generation_num) AS plan_generation_num,
    plan_handle,
    MIN (creation_time) AS creation_time, 
    MAX (last_execution_time) AS last_execution_time,
    SUM (execution_count) AS execution_count,
    SUM (total_worker_time) AS total_worker_time,
    MIN (min_worker_time) AS min_worker_time,           -- NULLable
    MAX (max_worker_time) AS max_worker_time,
    SUM (total_physical_reads) AS total_physical_reads,
    MIN (min_physical_reads) AS min_physical_reads,     -- NULLable
    MAX (max_physical_reads) AS max_physical_reads,
    SUM (total_logical_writes) AS total_logical_writes,
    MIN (min_logical_writes) AS min_logical_writes,     -- NULLable
    MAX (max_logical_writes) AS max_logical_writes,
    SUM (total_logical_reads) AS total_logical_reads,
    MIN (min_logical_reads) AS min_logical_reads,       -- NULLable
    MAX (max_logical_reads) AS max_logical_reads,
    SUM (total_clr_time) AS total_clr_time,
    MIN (min_clr_time) AS min_clr_time,                 -- NULLable
    MAX (max_clr_time) AS max_clr_time,
    SUM (total_elapsed_time) AS total_elapsed_time,
    MIN (min_elapsed_time) AS min_elapsed_time,         -- NULLable
    MAX (max_elapsed_time) AS max_elapsed_time,
    @p1 AS collection_time
FROM
(
    SELECT  
        [sql_handle],
        statement_start_offset,
        statement_end_offset,
        plan_generation_num,
        plan_handle,
        creation_time,
        last_execution_time,
        execution_count,
        total_worker_time,
        min_worker_time,
        max_worker_time,
        total_physical_reads,
        min_physical_reads,
        max_physical_reads,
        total_logical_writes,
        min_logical_writes,
        max_logical_writes,
        total_logical_reads,
        min_logical_reads,
        max_logical_reads,
        total_clr_time,
        min_clr_time,
        max_clr_time,
        total_elapsed_time,
        min_elapsed_time,
        max_elapsed_time 
    FROM sys.dm_exec_query_stats AS q
    UNION ALL 
    SELECT 
        r.[sql_handle],
        r.statement_start_offset,
        r.statement_end_offset,
        ISNULL (qs.plan_generation_num, 0) AS plan_generation_num,
        r.plan_handle,
        ISNULL (qs.creation_time, r.start_time) AS creation_time,
        r.start_time AS last_execution_time,
        1 AS execution_count,
        r.cpu_time AS total_worker_time,
        qs.min_worker_time,     -- min should not be influenced by in-progress queries
        r.cpu_time AS max_worker_time,
        r.reads AS total_physical_reads,
        qs.min_physical_reads,  -- min should not be influenced by in-progress queries
        r.reads AS max_physical_reads,
        r.writes AS total_logical_writes,
        qs.min_logical_writes,  -- min should not be influenced by in-progress queries
        r.writes AS max_logical_writes,
        r.logical_reads AS total_logical_reads,
        qs.min_logical_reads,   -- min should not be influenced by in-progress queries
        r.logical_reads AS max_logical_reads,
        qs.total_clr_time,      -- CLR time is not available in dm_exec_requests
        qs.min_clr_time,        -- CLR time is not available in dm_exec_requests
        qs.max_clr_time,        -- CLR time is not available in dm_exec_requests
        r.total_elapsed_time AS total_elapsed_time,
        qs.min_elapsed_time,    -- min should not be influenced by in-progress queries
        r.total_elapsed_time AS max_elapsed_time
    FROM sys.dm_exec_requests AS r 
    LEFT OUTER JOIN sys.dm_exec_query_stats AS qs ON r.plan_handle = qs.plan_handle AND r.statement_start_offset = qs.statement_start_offset 
        AND r.statement_end_offset = qs.statement_end_offset 
    WHERE r.sql_handle IS NOT NULL 
) AS query_stats 
OUTER APPLY sys.dm_exec_sql_text (sql_handle) AS sql
GROUP BY [sql_handle], plan_handle, statement_start_offset, statement_end_offset 
ORDER BY [sql_handle], plan_handle, statement_start_offset, statement_end_offset

Output query

snapshots.query_stats, snapshots.notable_query_text e snapshots.notable_query_plan