Övervaka prestanda för Microsoft Azure SQL Managed Instance med dynamiska hanteringsvyer

Gäller för:Azure SQL Managed Instance

Med Microsoft Azure SQL Managed Instance kan en delmängd av dynamiska hanteringsvyer (DMV:er) diagnostisera prestandaproblem som kan orsakas av blockerade eller långvariga frågor, resursflaskhalsar, dåliga frågeplaner och så vidare. Den här artikeln innehåller information om hur du identifierar vanliga prestandaproblem med hjälp av dynamiska hanteringsvyer.

Den här artikeln handlar om Azure SQL Managed Instance, se även Övervaka Prestanda för Microsoft Azure SQL Database med hjälp av dynamiska hanteringsvyer.

Behörigheter

För att köra frågor mot en dynamisk hanteringsvy i Azure SQL Managed Instance krävs behörigheter för VIEW SERVER STATE .

GRANT VIEW SERVER STATE TO database_user;

I en instans av SQL Server och i Azure SQL Managed Instance returnerar dynamiska hanteringsvyer servertillståndsinformation.

Identifiera problem med processorprestanda

Om CPU-förbrukningen är över 80 % under längre tidsperioder bör du överväga följande felsökningssteg:

Cpu-problemet inträffar nu

Om problemet uppstår just nu finns det två möjliga scenarier:

Många enskilda frågor som kumulativt förbrukar hög CPU

Använd följande fråga för att identifiera de viktigaste fråge-hashvärdena:

PRINT '-- top 10 Active CPU Consuming Queries (aggregated)--';
SELECT TOP 10 GETDATE() runtime, *
FROM (SELECT query_stats.query_hash, SUM(query_stats.cpu_time) 'Total_Request_Cpu_Time_Ms', SUM(logical_reads) 'Total_Request_Logical_Reads', MIN(start_time) 'Earliest_Request_start_Time', COUNT(*) 'Number_Of_Requests', SUBSTRING(REPLACE(REPLACE(MIN(query_stats.statement_text), CHAR(10), ' '), CHAR(13), ' '), 1, 256) AS "Statement_Text"
    FROM (SELECT req.*, SUBSTRING(ST.text, (req.statement_start_offset / 2)+1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)ELSE req.statement_end_offset END-req.statement_start_offset)/ 2)+1) AS statement_text
          FROM sys.dm_exec_requests AS req
                CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS ST ) AS query_stats
    GROUP BY query_hash) AS t
ORDER BY Total_Request_Cpu_Time_Ms DESC;

Tidskrävande frågor som använder processorn körs fortfarande

Använd följande fråga för att identifiera dessa frågor:

PRINT '--top 10 Active CPU Consuming Queries by sessions--';
SELECT TOP 10 req.session_id, req.start_time, cpu_time 'cpu_time_ms', OBJECT_NAME(ST.objectid, ST.dbid) 'ObjectName', SUBSTRING(REPLACE(REPLACE(SUBSTRING(ST.text, (req.statement_start_offset / 2)+1, ((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)ELSE req.statement_end_offset END-req.statement_start_offset)/ 2)+1), CHAR(10), ' '), CHAR(13), ' '), 1, 512) AS statement_text
FROM sys.dm_exec_requests AS req
    CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) AS ST
ORDER BY cpu_time DESC;
GO

Cpu-problemet inträffade tidigare

Om problemet har uppstått tidigare och du vill göra en rotorsaksanalys använder du Query Store. Användare med databasåtkomst kan använda T-SQL för att köra frågor mot Query Store-data. Standardkonfigurationer för Query Store använder en kornighet på 1 timme. Använd följande fråga för att titta på aktivitet för frågor med hög CPU-användning. Den här frågan returnerar de 15 mest processorkrävande frågorna. Kom ihåg att ändra rsi.start_time >= DATEADD(hour, -2, GETUTCDATE():

-- Top 15 CPU consuming queries by query hash
-- note that a query  hash can have many query id if not parameterized or not parameterized properly
-- it grabs a sample query text by min
WITH AggregatedCPU AS (SELECT q.query_hash, SUM(count_executions * avg_cpu_time / 1000.0) AS total_cpu_millisec, SUM(count_executions * avg_cpu_time / 1000.0)/ SUM(count_executions) AS avg_cpu_millisec, MAX(rs.max_cpu_time / 1000.00) AS max_cpu_millisec, MAX(max_logical_io_reads) max_logical_reads, COUNT(DISTINCT p.plan_id) AS number_of_distinct_plans, COUNT(DISTINCT p.query_id) AS number_of_distinct_query_ids, SUM(CASE WHEN rs.execution_type_desc='Aborted' THEN count_executions ELSE 0 END) AS Aborted_Execution_Count, SUM(CASE WHEN rs.execution_type_desc='Regular' THEN count_executions ELSE 0 END) AS Regular_Execution_Count, SUM(CASE WHEN rs.execution_type_desc='Exception' THEN count_executions ELSE 0 END) AS Exception_Execution_Count, SUM(count_executions) AS total_executions, MIN(qt.query_sql_text) AS sampled_query_text
                       FROM sys.query_store_query_text AS qt
                            JOIN sys.query_store_query AS q ON qt.query_text_id=q.query_text_id
                            JOIN sys.query_store_plan AS p ON q.query_id=p.query_id
                            JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id=p.plan_id
                            JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id=rs.runtime_stats_interval_id
                       WHERE rs.execution_type_desc IN ('Regular', 'Aborted', 'Exception')AND rsi.start_time>=DATEADD(HOUR, -2, GETUTCDATE())
                       GROUP BY q.query_hash), OrderedCPU AS (SELECT query_hash, total_cpu_millisec, avg_cpu_millisec, max_cpu_millisec, max_logical_reads, number_of_distinct_plans, number_of_distinct_query_ids, total_executions, Aborted_Execution_Count, Regular_Execution_Count, Exception_Execution_Count, sampled_query_text, ROW_NUMBER() OVER (ORDER BY total_cpu_millisec DESC, query_hash ASC) AS RN
                                                              FROM AggregatedCPU)
SELECT OD.query_hash, OD.total_cpu_millisec, OD.avg_cpu_millisec, OD.max_cpu_millisec, OD.max_logical_reads, OD.number_of_distinct_plans, OD.number_of_distinct_query_ids, OD.total_executions, OD.Aborted_Execution_Count, OD.Regular_Execution_Count, OD.Exception_Execution_Count, OD.sampled_query_text, OD.RN
FROM OrderedCPU AS OD
WHERE OD.RN<=15
ORDER BY total_cpu_millisec DESC;

När du har identifierat de problematiska frågorna är det dags att justera dessa frågor för att minska CPU-användningen. Om du inte har tid att justera frågorna kan du också välja att uppgradera SLO för den hanterade instansen för att lösa problemet.

Identifiera problem med I/O-prestanda

När du har problem med I/O-prestanda är följande väntetyper de som oftast associeras med I/O-problem:

  • PAGEIOLATCH_*

    För I/O-problem med datafiler (inklusive PAGEIOLATCH_SH, PAGEIOLATCH_EX, PAGEIOLATCH_UP). Om namnet på väntetypen har I/O i sig pekar det på ett I/O-problem. Om det inte finns någon I/O i väntenamnet för sidspärren pekar det på en annan typ av problem (till exempel tempdb konkurrens).

  • WRITE_LOG

    För I/O-problem med transaktionsloggar.

Om I/O-problemet inträffar just nu

Använd sys.dm_exec_requests eller sys.dm_os_waiting_tasks för att se wait_type och wait_time.

För alternativ 2 kan du använda följande fråga mot Query Store för buffertrelaterad I/O för att visa de senaste två timmarna av spårad aktivitet:

-- top queries that waited on buffer
-- note these are finished queries
WITH Aggregated AS (SELECT q.query_hash, SUM(total_query_wait_time_ms) total_wait_time_ms, SUM(total_query_wait_time_ms / avg_query_wait_time_ms) AS total_executions, MIN(qt.query_sql_text) AS sampled_query_text, MIN(wait_category_desc) AS wait_category_desc
                    FROM sys.query_store_query_text AS qt
                         JOIN sys.query_store_query AS q ON qt.query_text_id=q.query_text_id
                         JOIN sys.query_store_plan AS p ON q.query_id=p.query_id
                         JOIN sys.query_store_wait_stats AS waits ON waits.plan_id=p.plan_id
                         JOIN sys.query_store_runtime_stats_interval AS rsi ON rsi.runtime_stats_interval_id=waits.runtime_stats_interval_id
                    WHERE wait_category_desc='Buffer IO' AND rsi.start_time>=DATEADD(HOUR, -2, GETUTCDATE())
                    GROUP BY q.query_hash), Ordered AS (SELECT query_hash, total_executions, total_wait_time_ms, sampled_query_text, wait_category_desc, ROW_NUMBER() OVER (ORDER BY total_wait_time_ms DESC, query_hash ASC) AS RN
                                                        FROM Aggregated)
SELECT OD.query_hash, OD.total_executions, OD.total_wait_time_ms, OD.sampled_query_text, OD.wait_category_desc, OD.RN
FROM Ordered AS OD
WHERE OD.RN<=15
ORDER BY total_wait_time_ms DESC;
GO

Visa totalt antal logg-I/O för WRITELOG-väntetider

Om väntetypen är WRITELOGanvänder du följande fråga för att visa total logg-I/O efter -instruktion:

-- Top transaction log consumers
-- Adjust the time window by changing
-- rsi.start_time >= DATEADD(hour, -2, GETUTCDATE())
WITH AggregatedLogUsed
AS (SELECT q.query_hash,
           SUM(count_executions * avg_cpu_time / 1000.0) AS total_cpu_millisec,
           SUM(count_executions * avg_cpu_time / 1000.0) / SUM(count_executions) AS avg_cpu_millisec,
           SUM(count_executions * avg_log_bytes_used) AS total_log_bytes_used,
           MAX(rs.max_cpu_time / 1000.00) AS max_cpu_millisec,
           MAX(max_logical_io_reads) max_logical_reads,
           COUNT(DISTINCT p.plan_id) AS number_of_distinct_plans,
           COUNT(DISTINCT p.query_id) AS number_of_distinct_query_ids,
           SUM(   CASE
                      WHEN rs.execution_type_desc = 'Aborted' THEN
                          count_executions
                      ELSE
                          0
                  END
              ) AS Aborted_Execution_Count,
           SUM(   CASE
                      WHEN rs.execution_type_desc = 'Regular' THEN
                          count_executions
                      ELSE
                          0
                  END
              ) AS Regular_Execution_Count,
           SUM(   CASE
                      WHEN rs.execution_type_desc = 'Exception' THEN
                          count_executions
                      ELSE
                          0
                  END
              ) AS Exception_Execution_Count,
           SUM(count_executions) AS total_executions,
           MIN(qt.query_sql_text) AS sampled_query_text
    FROM sys.query_store_query_text AS qt
        JOIN sys.query_store_query AS q
            ON qt.query_text_id = q.query_text_id
        JOIN sys.query_store_plan AS p
            ON q.query_id = p.query_id
        JOIN sys.query_store_runtime_stats AS rs
            ON rs.plan_id = p.plan_id
        JOIN sys.query_store_runtime_stats_interval AS rsi
            ON rsi.runtime_stats_interval_id = rs.runtime_stats_interval_id
    WHERE rs.execution_type_desc IN ( 'Regular', 'Aborted', 'Exception' )
          AND rsi.start_time >= DATEADD(HOUR, -2, GETUTCDATE())
    GROUP BY q.query_hash),
     OrderedLogUsed
AS (SELECT query_hash,
           total_log_bytes_used,
           number_of_distinct_plans,
           number_of_distinct_query_ids,
           total_executions,
           Aborted_Execution_Count,
           Regular_Execution_Count,
           Exception_Execution_Count,
           sampled_query_text,
           ROW_NUMBER() OVER (ORDER BY total_log_bytes_used DESC, query_hash ASC) AS RN
    FROM AggregatedLogUsed)
SELECT OD.total_log_bytes_used,
       OD.number_of_distinct_plans,
       OD.number_of_distinct_query_ids,
       OD.total_executions,
       OD.Aborted_Execution_Count,
       OD.Regular_Execution_Count,
       OD.Exception_Execution_Count,
       OD.sampled_query_text,
       OD.RN
FROM OrderedLogUsed AS OD
WHERE OD.RN <= 15
ORDER BY total_log_bytes_used DESC;
GO

Identifiera tempdb prestandaproblem

När du identifierar I/O-prestandaproblem är de vanligaste väntetyperna som är associerade med tempdb problem (inte PAGEIOLATCH_*).PAGELATCH_* Väntetider betyder dock PAGELATCH_* inte alltid att du har tempdb konkurrens. Det kan också bero på konkurrens om en datasida med användarobjekt på grund av konkurrerande begäranden som görs mot samma datasida. Om du vill bekräfta tempdb konkurrensen ytterligare använder du sys.dm_exec_requests för att bekräfta att värdet wait_resource börjar med 2:x:y där 2 är tempdb databas-ID, x är fil-ID och y är sid-ID.

För tempdb konkurrens är en vanlig metod att minska eller skriva om programkod som förlitar sig på tempdb. Vanliga tempdb användningsområden är:

  • Temporära tabeller
  • Tabellvariabler
  • Tabellvärdesparametrar
  • Användning av versionsarkiv (associerad med långvariga transaktioner)
  • Frågor som har frågeplaner som använder sorteringar, hash-kopplingar och buffertar

De vanligaste frågorna som använder tabellvariabler och temporära tabeller

Använd följande fråga för att identifiera de vanligaste frågorna som använder tabellvariabler och temporära tabeller:

SELECT plan_handle, execution_count, query_plan
INTO #tmpPlan
FROM sys.dm_exec_query_stats
     CROSS APPLY sys.dm_exec_query_plan(plan_handle);
GO

WITH XMLNAMESPACES('http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS sp)
SELECT plan_handle, stmt.stmt_details.value('@Database', 'varchar(max)') 'Database', stmt.stmt_details.value('@Schema', 'varchar(max)') 'Schema', stmt.stmt_details.value('@Table', 'varchar(max)') 'table'
INTO #tmp2
FROM(SELECT CAST(query_plan AS XML) sqlplan, plan_handle FROM #tmpPlan) AS p
    CROSS APPLY sqlplan.nodes('//sp:Object') AS stmt(stmt_details);
GO

SELECT t.plan_handle, [Database], [Schema], [table], execution_count
FROM(SELECT DISTINCT plan_handle, [Database], [Schema], [table]
     FROM #tmp2
     WHERE [table] LIKE '%@%' OR [table] LIKE '%#%') AS t
    JOIN #tmpPlan AS t2 ON t.plan_handle=t2.plan_handle;

Identifiera tidskrävande transaktioner

Använd följande fråga för att identifiera långvariga transaktioner. Tidskrävande transaktioner förhindrar rensning av versionsarkiv.

SELECT DB_NAME(dtr.database_id) 'database_name',
       sess.session_id,
       atr.name AS 'tran_name',
       atr.transaction_id,
       transaction_type,
       transaction_begin_time,
       database_transaction_begin_time, 
       transaction_state,
       is_user_transaction,
       sess.open_transaction_count,
       TRIM(REPLACE(
                REPLACE(
                            SUBSTRING(
                                        SUBSTRING(
                                                    txt.text,
                                                    (req.statement_start_offset / 2) + 1,
                                                    ((CASE req.statement_end_offset
                                                            WHEN -1 THEN
                                                                DATALENGTH(txt.text)
                                                            ELSE
                                                                req.statement_end_offset
                                                        END - req.statement_start_offset
                                                    ) / 2
                                                    ) + 1
                                                ),
                                        1,
                                        1000
                                    ),
                            CHAR(10),
                            ' '
                        ),
                CHAR(13),
                ' '
            )
            ) Running_stmt_text,
       recenttxt.text 'MostRecentSQLText'
FROM sys.dm_tran_active_transactions AS atr
    INNER JOIN sys.dm_tran_database_transactions AS dtr
        ON dtr.transaction_id = atr.transaction_id
    LEFT JOIN sys.dm_tran_session_transactions AS sess
        ON sess.transaction_id = atr.transaction_id
    LEFT JOIN sys.dm_exec_requests AS req
        ON req.session_id = sess.session_id
           AND req.transaction_id = sess.transaction_id
    LEFT JOIN sys.dm_exec_connections AS conn
        ON sess.session_id = conn.session_id
    OUTER APPLY sys.dm_exec_sql_text(req.sql_handle) AS txt
    OUTER APPLY sys.dm_exec_sql_text(conn.most_recent_sql_handle) AS recenttxt
WHERE atr.transaction_type != 2
      AND sess.session_id != @@spid
ORDER BY start_time ASC;

Identifiera problem med att bevilja vänteprestanda för minne

Om din högsta väntetyp är RESOURCE_SEMAHPORE och du inte har problem med hög CPU-användning kan du ha problem med att bevilja minne.

Ta reda på om en RESOURCE_SEMAHPORE väntetid är en toppvänte

Använd följande fråga för att avgöra om en RESOURCE_SEMAHPORE väntetid är en toppvänte

SELECT wait_type,
       SUM(wait_time) AS total_wait_time_ms
FROM sys.dm_exec_requests AS req
    JOIN sys.dm_exec_sessions AS sess
        ON req.session_id = sess.session_id
WHERE is_user_process = 1
GROUP BY wait_type
ORDER BY SUM(wait_time) DESC;

Identifiera höga minneskrävande instruktioner

Om det uppstår minnesfel kan du läsa sys.dm_os_out_of_memory_events.

Använd följande fråga för att identifiera höga minneskrävande instruktioner:

SELECT IDENTITY(INT, 1, 1) rowId,
    CAST(query_plan AS XML) query_plan,
    p.query_id
INTO #tmp
FROM sys.query_store_plan AS p
    JOIN sys.query_store_runtime_stats AS r
        ON p.plan_id = r.plan_id
    JOIN sys.query_store_runtime_stats_interval AS i
        ON r.runtime_stats_interval_id = i.runtime_stats_interval_id
WHERE start_time > '2018-10-11 14:00:00.0000000'
      AND end_time < '2018-10-17 20:00:00.0000000';
GO
;WITH cte
AS (SELECT query_id,
        query_plan,
        m.c.value('@SerialDesiredMemory', 'INT') AS SerialDesiredMemory
    FROM #tmp AS t
        CROSS APPLY t.query_plan.nodes('//*:MemoryGrantInfo[@SerialDesiredMemory[. > 0]]') AS m(c) )
SELECT TOP 50
    cte.query_id,
    t.query_sql_text,
    cte.query_plan,
    CAST(SerialDesiredMemory / 1024. AS DECIMAL(10, 2)) SerialDesiredMemory_MB
FROM cte
    JOIN sys.query_store_query AS q
        ON cte.query_id = q.query_id
    JOIN sys.query_store_query_text AS t
        ON q.query_text_id = t.query_text_id
ORDER BY SerialDesiredMemory DESC;

Identifiera minnestilldelarna

Använd följande fråga för att identifiera de 10 främsta aktiva minnestilldelningarna:

SELECT TOP 10
    CONVERT(VARCHAR(30), GETDATE(), 121) AS runtime,
       r.session_id,
       r.blocking_session_id,
       r.cpu_time,
       r.total_elapsed_time,
       r.reads,
       r.writes,
       r.logical_reads,
       r.row_count,
       wait_time,
       wait_type,
       r.command,
       OBJECT_NAME(txt.objectid, txt.dbid) 'Object_Name',
       TRIM(REPLACE(
                REPLACE(
                            SUBSTRING(
                                        SUBSTRING(
                                                    text,
                                                    (r.statement_start_offset / 2) + 1,
                                                    ((CASE r.statement_end_offset
                                                            WHEN -1 THEN
                                                                DATALENGTH(text)
                                                            ELSE
                                                                r.statement_end_offset
                                                        END - r.statement_start_offset
                                                    ) / 2
                                                    ) + 1
                                                ),
                                        1,
                                        1000
                                    ),
                            CHAR(10),
                            ' '
                        ),
                CHAR(13),
                ' '
            )
            ) stmt_text,
       mg.dop,                                               --Degree of parallelism
       mg.request_time,                                      --Date and time when this query requested the memory grant.
       mg.grant_time,                                        --NULL means memory has not been granted
       mg.requested_memory_kb / 1024.0 requested_memory_mb,  --Total requested amount of memory in megabytes
       mg.granted_memory_kb / 1024.0 AS granted_memory_mb,   --Total amount of memory actually granted in megabytes. NULL if not granted
       mg.required_memory_kb / 1024.0 AS required_memory_mb, --Minimum memory required to run this query in megabytes.
       max_used_memory_kb / 1024.0 AS max_used_memory_mb,
       mg.query_cost,                                        --Estimated query cost.
       mg.timeout_sec,                                       --Time-out in seconds before this query gives up the memory grant request.
       mg.resource_semaphore_id,                             --Non-unique ID of the resource semaphore on which this query is waiting.
       mg.wait_time_ms,                                      --Wait time in milliseconds. NULL if the memory is already granted.
       CASE mg.is_next_candidate --Is this process the next candidate for a memory grant
           WHEN 1 THEN
               'Yes'
           WHEN 0 THEN
               'No'
           ELSE
               'Memory has been granted'
       END AS 'Next Candidate for Memory Grant',
       qp.query_plan
FROM sys.dm_exec_requests AS r
    JOIN sys.dm_exec_query_memory_grants AS mg
        ON r.session_id = mg.session_id
           AND r.request_id = mg.request_id
    CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS txt
    CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp
ORDER BY mg.granted_memory_kb DESC;

Beräkna databas- och objektstorlekar

Följande fråga returnerar databasens storlek (i MB):

-- Calculates the size of the database.
SELECT SUM(CAST(FILEPROPERTY(name, 'SpaceUsed') AS bigint) * 8192.) / 1024 / 1024 AS DatabaseSizeInMB
FROM sys.database_files
WHERE type_desc = 'ROWS';
GO

Följande fråga returnerar storleken på enskilda objekt (i MB) i databasen:

-- Calculates the size of individual database objects.
SELECT sys.objects.name, SUM(reserved_page_count) * 8.0 / 1024
FROM sys.dm_db_partition_stats, sys.objects
WHERE sys.dm_db_partition_stats.object_id = sys.objects.object_id
GROUP BY sys.objects.name;
GO

Övervaka anslutningar

Du kan använda vyn sys.dm_exec_connections för att hämta information om anslutningar som upprättats till en specifik hanterad instans och information om varje anslutning. Dessutom är vyn sys.dm_exec_sessions användbar när du hämtar information om alla aktiva användaranslutningar och interna uppgifter.

Följande fråga hämtar information om den aktuella anslutningen:

SELECT
    c.session_id, c.net_transport, c.encrypt_option,
    c.auth_scheme, s.host_name, s.program_name,
    s.client_interface_name, s.login_name, s.nt_domain,
    s.nt_user_name, s.original_login_name, c.connect_time,
    s.login_time
FROM sys.dm_exec_connections AS c
JOIN sys.dm_exec_sessions AS s
    ON c.session_id = s.session_id
WHERE c.session_id = @@SPID;

Övervaka resursanvändning

Du kan övervaka resursanvändningen med hjälp av Query Store, precis som i SQL Server.

Du kan också övervaka användningen med hjälp av sys.dm_db_resource_stats och sys.server_resource_stats.

sys.dm_db_resource_stats

Du kan använda vyn sys.dm_db_resource_stats i varje databas. Vyn sys.dm_db_resource_stats visar senaste resursanvändningsdata i förhållande till tjänstnivån. Genomsnittliga procentandelar för CPU, data-I/O, loggskrivningar och minne registreras var 15:e sekund och underhålls i 1 timme.

Eftersom den här vyn ger en mer detaljerad titt på resursanvändningen använder du sys.dm_db_resource_stats först för alla aktuella tillståndsanalyser eller felsökningar. Den här frågan visar till exempel den genomsnittliga och högsta resursanvändningen för den aktuella databasen under den senaste timmen:

SELECT  
    AVG(avg_cpu_percent) AS 'Average CPU use in percent',
    MAX(avg_cpu_percent) AS 'Maximum CPU use in percent',
    AVG(avg_data_io_percent) AS 'Average data IO in percent',
    MAX(avg_data_io_percent) AS 'Maximum data IO in percent',
    AVG(avg_log_write_percent) AS 'Average log write use in percent',
    MAX(avg_log_write_percent) AS 'Maximum log write use in percent',
    AVG(avg_memory_usage_percent) AS 'Average memory use in percent',
    MAX(avg_memory_usage_percent) AS 'Maximum memory use in percent'
FROM sys.dm_db_resource_stats;  

Andra frågor finns i exemplen i sys.dm_db_resource_stats.

sys.server_resource_stats

Du kan använda sys.server_resource_stats för att returnera CPU-användning, I/O och lagringsdata för en Hanterad Azure SQL-instans. Data samlas in och aggregeras inom fem minuters intervall. Det finns en rad för rapportering var 15:e sekund. De data som returneras omfattar CPU-användning, lagringsstorlek, I/O-användning och SKU för hanterad instans. Historiska data bevaras i cirka 14 dagar.

Exemplen visar olika sätt att använda sys.server_resource_stats katalogvyn för att få information om hur din instans använder resurser.

  1. I följande exempel returneras den genomsnittliga CPU-användningen under de senaste sju dagarna:

    DECLARE @s datetime;  
    DECLARE @e datetime;  
    SET @s= DateAdd(d,-7,GetUTCDate());  
    SET @e= GETUTCDATE();  
    SELECT AVG(avg_cpu_percent) AS Average_Compute_Utilization   
    FROM sys.server_resource_stats   
    WHERE start_time BETWEEN @s AND @e;
    GO
    
  2. I följande exempel returneras det genomsnittliga lagringsutrymme som används av din instans per dag för att möjliggöra tillväxttrendanalys:

    DECLARE @s datetime;  
    DECLARE @e datetime;  
    SET @s= DateAdd(d,-7,GetUTCDate());  
    SET @e= GETUTCDATE();  
    SELECT Day = convert(date, start_time), AVG(storage_space_used_mb) AS Average_Space_Used_mb
    FROM sys.server_resource_stats   
    WHERE start_time BETWEEN @s AND @e
    GROUP BY convert(date, start_time)
    ORDER BY convert(date, start_time);
    GO
    

Maximalt antal samtidiga begäranden

Om du vill se det aktuella antalet samtidiga begäranden kör du den här Transact-SQL-frågan i databasen:

SELECT COUNT(*) AS [Concurrent_Requests]
FROM sys.dm_exec_requests R;

Om du vill analysera arbetsbelastningen för en enskild databas ändrar du den här frågan så att den filtrerar på den specifika databas som du vill analysera. Om du till exempel har en databas med namnet MyDatabasereturnerar den här Transact-SQL-frågan antalet samtidiga begäranden i databasen:

SELECT COUNT(*) AS [Concurrent_Requests]
FROM sys.dm_exec_requests R
INNER JOIN sys.databases D ON D.database_id = R.database_id
AND D.name = 'MyDatabase';

Det här är bara en ögonblicksbild vid en enda tidpunkt. För att få en bättre förståelse för dina krav på arbetsbelastningar och samtidiga begäranden måste du samla in många exempel över tid.

Maximalt antal samtidiga inloggningar

Du kan analysera användar- och programmönster för att få en uppfattning om inloggningsfrekvensen. Du kan också köra verkliga belastningar i en testmiljö för att se till att du inte når den här eller andra gränser som vi diskuterar i den här artikeln. Det finns inte en enda fråga eller dynamisk hanteringsvy (DMV) som kan visa antalet samtidiga inloggningar eller historik.

Om flera klienter använder samma anslutningssträng autentiserar tjänsten varje inloggning. Om 10 användare samtidigt ansluter till en databas med samma användarnamn och lösenord skulle det finnas 10 samtidiga inloggningar. Den här gränsen gäller endast för varaktigheten för inloggningen och autentiseringen. Om samma 10 användare ansluter till databasen sekventiellt blir antalet samtidiga inloggningar aldrig större än 1.

Maximalt antal sessioner

Om du vill se antalet aktuella aktiva sessioner kör du den här Transact-SQL-frågan i databasen:

SELECT COUNT(*) AS [Sessions]
FROM sys.dm_exec_connections;

Om du analyserar en SQL Server-arbetsbelastning ändrar du frågan så att den fokuserar på en specifik databas. Den här frågan hjälper dig att fastställa möjliga sessionsbehov för databasen om du överväger att flytta den till Azure.

SELECT COUNT(*) AS [Sessions]
FROM sys.dm_exec_connections C
INNER JOIN sys.dm_exec_sessions S ON (S.session_id = C.session_id)
INNER JOIN sys.databases D ON (D.database_id = S.database_id)
WHERE D.name = 'MyDatabase';

Återigen returnerar dessa frågor ett antal tidpunkter. Om du samlar in flera exempel över tid har du den bästa förståelsen för din sessionsanvändning.

Övervaka frågeprestanda

Långsamma eller tidskrävande frågor kan förbruka betydande systemresurser. Det här avsnittet visar hur du använder dynamiska hanteringsvyer för att identifiera några vanliga problem med frågeprestanda.

Hitta de främsta N-frågorna

I följande exempel returneras information om de fem vanligaste frågorna rangordnade efter genomsnittlig CPU-tid. Det här exemplet aggregerar frågorna enligt deras frågehash, så att logiskt likvärdiga frågor grupperas efter deras kumulativa resursförbrukning.

SELECT TOP 5 query_stats.query_hash AS "Query Hash",
    SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) AS "Avg CPU Time",
     MIN(query_stats.statement_text) AS "Statement Text"
FROM
    (SELECT QS.*,
        SUBSTRING(ST.text, (QS.statement_start_offset/2) + 1,
            ((CASE statement_end_offset
                WHEN -1 THEN DATALENGTH(ST.text)
                ELSE QS.statement_end_offset END
            - QS.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS QS
CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle) as ST) as query_stats
GROUP BY query_stats.query_hash
ORDER BY 2 DESC;

Övervaka blockerade frågor

Långsamma eller långvariga frågor kan bidra till överdriven resursförbrukning och vara en följd av blockerade frågor. Orsaken till blockeringen kan vara dålig programdesign, dåliga frågeplaner, bristen på användbara index och så vidare. Du kan använda vyn sys.dm_tran_locks för att hämta information om den aktuella låsningsaktiviteten i databasen. Exempel på kod finns i sys.dm_tran_locks. Mer information om felsökning av blockering finns i Förstå och lösa azure SQL-blockeringsproblem.

Övervaka dödlägen

I vissa fall kan två eller flera frågor blockera varandra ömsesidigt, vilket resulterar i ett dödläge.

Du kan skapa en Extended Events-spårning av en databas för att samla in dödlägeshändelser och sedan hitta relaterade frågor och deras körningsplaner i Query Store.

Information om Azure SQL Managed Instance finns i Deadlock-verktygen i guiden Deadlocks (Dödlägen).

Övervaka frågeplaner

En ineffektiv frågeplan kan också öka CPU-förbrukningen. I följande exempel används vyn sys.dm_exec_query_stats för att avgöra vilken fråga som använder den mest kumulativa processorn.

SELECT
    highest_cpu_queries.plan_handle,
    highest_cpu_queries.total_worker_time,
    q.dbid,
    q.objectid,
    q.number,
    q.encrypted,
    q.[text]
FROM
    (SELECT TOP 50
        qs.plan_handle,
        qs.total_worker_time
    FROM
        sys.dm_exec_query_stats qs
ORDER BY qs.total_worker_time desc) AS highest_cpu_queries
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS q
ORDER BY highest_cpu_queries.total_worker_time DESC;

Andra övervakningsalternativ

Övervaka med SQL Insights (förhandsversion)

Azure Monitor SQL Insights (förhandsversion) är ett verktyg för att övervaka instanser av Azure SQL Managed Instance, databaser i Azure SQL Database och SQL Server på virtuella Azure SQL-datorer. Den här tjänsten använder en fjärragent för att samla in data från dynamiska hanteringsvyer (DMV:er) och dirigerar data till Azure Log Analytics, där de kan övervakas och analyseras. Du kan visa dessa data från Azure Monitor i angivna vyer eller komma åt loggdata direkt för att köra frågor och analysera trender. Information om hur du börjar använda Azure Monitor SQL Insights (förhandsversion) finns i Aktivera SQL Insights (förhandsversion).

Övervaka med Azure Monitor

Azure Monitor tillhandahåller en mängd olika grupper, mått och slutpunkter för övervakning av Azure SQL Managed Instance. Mer information finns i Övervaka Azure SQL Managed Instance med Azure Monitor. Azure SQL Analytics (förhandsversion) är en integrering med Azure Monitor, där många övervakningslösningar inte längre är i aktiv utveckling. Fler övervakningsalternativ finns i Övervakning och prestandajustering i Azure SQL Managed Instance och Azure SQL Database.

Se även

Nästa steg