Monitorowanie wydajności Microsoft Azure SQL Database i wystąpienia zarządzanego usługi Azure SQL przy użyciu dynamicznych widoków zarządzaniaMonitoring Microsoft Azure SQL Database and Azure SQL Managed Instance performance using dynamic management views

dotyczy:  tak Azure SQL Database  tak, wystąpienie zarządzane Azure SQLAPPLIES TO: yesAzure SQL Database yesAzure SQL Managed Instance

Microsoft Azure SQL Database i wystąpienie zarządzane usługi Azure SQL umożliwiają podzbiór dynamicznych widoków zarządzania do diagnozowania problemów z wydajnością, które mogą być spowodowane przez zablokowane lub długotrwałe zapytania, wąskie gardła zasobów, słabe plany zapytań i tak dalej.Microsoft Azure SQL Database and Azure SQL Managed Instance enable a subset of dynamic management views to diagnose performance problems, which might be caused by blocked or long-running queries, resource bottlenecks, poor query plans, and so on. Ten temat zawiera informacje dotyczące wykrywania typowych problemów z wydajnością przy użyciu dynamicznych widoków zarządzania.This topic provides information on how to detect common performance problems by using dynamic management views.

Microsoft Azure SQL Database i wystąpienie zarządzane usługi Azure SQL częściowo obsługują trzy kategorie dynamicznych widoków zarządzania:Microsoft Azure SQL Database and Azure SQL Managed Instance partially support three categories of dynamic management views:

  • Dynamiczne widoki zarządzania powiązane z bazami danych.Database-related dynamic management views.
  • Dynamiczne widoki zarządzania powiązane z wykonywaniem.Execution-related dynamic management views.
  • Dynamiczne widoki zarządzania powiązane z transakcjami.Transaction-related dynamic management views.

Aby uzyskać szczegółowe informacje o widokach zarządzania dynamicznego, zobacz dynamiczne widoki zarządzania i funkcje (Transact-SQL).For detailed information on dynamic management views, see Dynamic Management Views and Functions (Transact-SQL).

UprawnieniaPermissions

W programie Azure SQL Database wykonywanie zapytania dotyczącego dynamicznego widoku zarządzania wymaga uprawnień Wyświetlanie stanu bazy danych .In Azure SQL Database, querying a dynamic management view requires VIEW DATABASE STATE permissions. Uprawnienie Wyświetlanie stanu bazy danych zwraca informacje o wszystkich obiektach w bieżącej bazie danych.The VIEW DATABASE STATE permission returns information about all objects within the current database. Aby udzielić uprawnienia do wyświetlania stanu bazy danych określonemu użytkownikowi bazy danych, uruchom następujące zapytanie:To grant the VIEW DATABASE STATE permission to a specific database user, run the following query:

GRANT VIEW DATABASE STATE TO database_user;

W wystąpieniu zarządzanym usługi Azure SQL wykonywanie zapytania dotyczącego dynamicznego widoku zarządzania wymaga uprawnień do wyświetlania stanu serwera .In Azure SQL Managed Instance, querying a dynamic management view requires VIEW SERVER STATE permissions. Aby uzyskać więcej informacji, zobacz dynamiczne zarządzanie dynamicznymi widokami.For more information, see System Dynamic Management Views.

W wystąpieniu SQL Server i w wystąpieniu zarządzanym Azure SQL, dynamiczne widoki zarządzania zwracają informacje o stanie serwera.In an instance of SQL Server and in Azure SQL Managed Instance, dynamic management views return server state information. W Azure SQL Database zwracają informacje dotyczące tylko bieżącej logicznej bazy danych.In Azure SQL Database, they return information regarding your current logical database only.

Ten artykuł zawiera kolekcję zapytań DMV, które można wykonać za pomocą SQL Server Management Studio lub Azure Data Studio w celu wykrycia następujących typów problemów z wydajnością zapytań:This article contains a collection of DMV queries that you can execute using SQL Server Management Studio or Azure Data Studio to detect the following types of query performance issues:

Identyfikowanie problemów z wydajnością procesora CPUIdentify CPU performance issues

Jeśli użycie procesora CPU jest powyżej 80% przez dłuższy czas, należy wziąć pod uwagę następujące kroki rozwiązywania problemów:If CPU consumption is above 80% for extended periods of time, consider the following troubleshooting steps:

Problem z procesorem CPU występuje terazThe CPU issue is occurring now

Jeśli problem występuje już teraz, istnieją dwa możliwe scenariusze:If issue is occurring right now, there are two possible scenarios:

Wiele indywidualnych zapytań, które łącznie zużywają duże użycie procesora CPUMany individual queries that cumulatively consume high CPU

Użyj następującego zapytania, aby zidentyfikować Najważniejsze skróty zapytania:Use the following query to identify top query hashes:

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;

Długotrwałe zapytania, które zużywają procesor CPU, są nadal uruchomioneLong running queries that consume CPU are still running

Użyj następującego zapytania, aby zidentyfikować te zapytania:Use the following query to identify these queries:

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

Wystąpił problem z procesorem CPU w przeszłościThe CPU issue occurred in the past

Jeśli problem wystąpił w przeszłości i chcesz przeprowadzić analizę głównej przyczyny, użyj magazynu zapytań.If the issue occurred in the past and you want to do root cause analysis, use Query Store. Użytkownicy z dostępem do bazy danych mogą używać języka T-SQL do wykonywania zapytań dotyczących danych magazynu zapytań.Users with database access can use T-SQL to query Query Store data. Domyślne konfiguracje magazynu zapytań korzystają z stopnia szczegółowości 1 godziny.Query Store default configurations use a granularity of 1 hour. Użyj następującego zapytania, aby przyjrzeć się działaniu w przypadku dużych zapytań zużywających procesor CPU.Use the following query to look at activity for high CPU consuming queries. To zapytanie zwraca 15 najważniejszych zapytań zużywających procesor CPU.This query returns the top 15 CPU consuming queries. Pamiętaj, aby zmienić rsi.start_time >= DATEADD(hour, -2, GETUTCDATE() :Remember to change 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;

Po zidentyfikowaniu problemów z zapytaniami czasowo dostroić te zapytania, aby zmniejszyć wykorzystanie procesora CPU.Once you identify the problematic queries, it's time to tune those queries to reduce CPU utilization. Jeśli nie masz czasu na dostosowanie zapytań, możesz również uaktualnić cel bazy danych w celu obejścia tego problemu.If you don't have time to tune the queries, you may also choose to upgrade the SLO of the database to work around the issue.

Identyfikowanie problemów z wydajnością we/wyIdentify IO performance issues

Podczas identyfikowania problemów dotyczących wydajności operacji we/wy najważniejsze typy oczekiwania skojarzone z problemami we/wy są następujące:When identifying IO performance issues, the top wait types associated with IO issues are:

  • PAGEIOLATCH_*

    W przypadku problemów we/wy pliku danych (w tym PAGEIOLATCH_SH , PAGEIOLATCH_EX , PAGEIOLATCH_UP ).For data file IO issues (including PAGEIOLATCH_SH, PAGEIOLATCH_EX, PAGEIOLATCH_UP). Jeśli nazwa typu oczekiwania zawiera we /wy , wskazuje na problem we/wy.If the wait type name has IO in it, it points to an IO issue. Jeśli nie ma operacji we/wy w nazwie oczekiwania zamka strony, wskazuje na inny typ problemu (na przykład rywalizacja o bazę danych tempdb).If there is no IO in the page latch wait name, it points to a different type of problem (for example, tempdb contention).

  • WRITE_LOG

    W przypadku problemów z operacjami we/wy dziennika transakcji.For transaction log IO issues.

Jeśli problem we/wy występuje już terazIf the IO issue is occurring right now

Użyj widoku sys. dm_exec_requests lub sys. dm_os_waiting_tasks , aby zobaczyć wait_type i wait_time .Use the sys.dm_exec_requests or sys.dm_os_waiting_tasks to see the wait_type and wait_time.

Identyfikowanie użycia operacji we/wy danych i dziennikaIdentify data and log IO usage

Użyj następującego zapytania, aby zidentyfikować dane i użycie operacji we/wy dziennika.Use the following query to identify data and log IO usage. Jeśli operacje we/wy danych lub dziennika są powyżej 80%, oznacza to, że użytkownicy korzystali z dostępnych operacji we/wy dla warstwy usług SQL Database.If the data or log IO is above 80%, it means users have used the available IO for the SQL Database service tier.

SELECT end_time, avg_data_io_percent, avg_log_write_percent
FROM sys.dm_db_resource_stats
ORDER BY end_time DESC;

Jeśli limit operacji we/wy został osiągnięty, dostępne są dwie opcje:If the IO limit has been reached, you have two options:

  • Opcja 1: uaktualnianie rozmiaru obliczeń lub warstwy usługOption 1: Upgrade the compute size or service tier
  • Opcja 2: Identyfikowanie i dostrajanie zapytań zużywających najwięcej operacji we/wy.Option 2: Identify and tune the queries consuming the most IO.

W przypadku opcji 2 można użyć następującego zapytania względem magazynu zapytań dla operacji we/wy, aby wyświetlić ostatnie dwie godziny śledzonego działania:For option 2, you can use the following query against Query Store for buffer-related IO to view the last two hours of tracked activity:

-- 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

Wyświetl łączny limit operacji we/wy dziennika dla WRITELOGView total log IO for WRITELOG waits

Jeśli typ oczekiwania to WRITELOG , użyj następującego zapytania, aby wyświetlić łączną liczbę operacji we/wy dziennika:If the wait type is WRITELOG, use the following query to view total log IO by statement:

-- 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

Identyfikowanie tempdb problemów z wydajnościąIdentify tempdb performance issues

W przypadku identyfikowania problemów dotyczących wydajności operacji we/wy najważniejsze typy oczekiwania skojarzone z tempdb problemami to PAGELATCH_* (nie PAGEIOLATCH_* ).When identifying IO performance issues, the top wait types associated with tempdb issues is PAGELATCH_* (not PAGEIOLATCH_*). Jednak PAGELATCH_* oczekiwania nie zawsze oznaczają tempdb rywalizację.However, PAGELATCH_* waits do not always mean you have tempdb contention. Taka odczekanie może również oznaczać, że masz zawartość strony danych obiektu użytkownika z powodu współbieżnych żądań przeznaczonych dla tej samej strony danych.This wait may also mean that you have user-object data page contention due to concurrent requests targeting the same data page. Aby dodatkowo potwierdzić tempdb rywalizację, użyj wykazu sys. dm_exec_requests , aby potwierdzić, że wait_resource wartość zaczyna się od, 2:x:y gdzie 2 jest tempdb identyfikatorem bazy danych, x jest identyfikatorem pliku i jest identyfikatorem y strony.To further confirm tempdb contention, use sys.dm_exec_requests to confirm that the wait_resource value begins with 2:x:y where 2 is tempdb is the database ID, x is the file ID, and y is the page ID.

W przypadku rywalizacji o bazę danych tempdb wspólna metoda polega na zmniejszeniu lub ponownym zapisaniu kodu aplikacji, na którym bazuje tempdb .For tempdb contention, a common method is to reduce or re-write application code that relies on tempdb. Typowe tempdb obszary użycia obejmują:Common tempdb usage areas include:

  • Tabele tymczasoweTemp tables
  • Zmienne tabeliTable variables
  • Parametry z wartościami przechowywanymi w tabeliTable-valued parameters
  • Użycie magazynu wersji (powiązane z długotrwałymi transakcjami)Version store usage (specifically associated with long running transactions)
  • Zapytania z planami zapytania, które używają sortowania, sprzężeń skrótów i buforówQueries that have query plans that use sorts, hash joins, and spools

Najpopularniejsze zapytania, które używają zmiennych tabeli i tabel tymczasowychTop queries that use table variables and temporary tables

Użyj następującego zapytania, aby zidentyfikować najpopularniejsze zapytania, które używają zmiennych tabeli i tabel tymczasowych:Use the following query to identify top queries that use table variables and temporary tables:

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;

Zidentyfikuj długotrwałe transakcjeIdentify long running transactions

Użyj następującego zapytania, aby zidentyfikować długotrwałe transakcje.Use the following query to identify long running transactions. Długotrwałe transakcje uniemożliwiają czyszczenie magazynu wersji.Long running transactions prevent version store cleanup.

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,
       LTRIM(RTRIM(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;

Identyfikuj problemy z wydajnością odczekania pamięciIdentify memory grant wait performance issues

Jeśli typ oczekiwania to RESOURCE_SEMAHPORE i nie masz wysokiego problemu dotyczącego użycia procesora CPU, może wystąpić problem z przydzieleniem pamięci.If your top wait type is RESOURCE_SEMAHPORE and you don't have a high CPU usage issue, you may have a memory grant waiting issue.

Określanie, czy RESOURCE_SEMAHPORE oczekiwanie jest oczekiwanie na początkuDetermine if a RESOURCE_SEMAHPORE wait is a top wait

Użyj następującego zapytania, aby określić, czy RESOURCE_SEMAHPORE oczekiwanie jest oczekiwanie na początkuUse the following query to determine if a RESOURCE_SEMAHPORE wait is a top wait

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;

Wysoce czasochłonne instrukcje tożsamościIdentity high memory-consuming statements

Użyj następującego zapytania, aby zidentyfikować następujące instrukcje zużywające pamięć:Use the following query to identify high memory-consuming statements:

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;

Zidentyfikuj 10 najważniejszych przydziałów pamięciIdentify the top 10 active memory grants

Użyj następującego zapytania, aby zidentyfikować 10 najważniejszych przydziałów pamięci:Use the following query to identify the top 10 active memory grants:

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',
       LTRIM(RTRIM(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;

Obliczanie rozmiarów baz danych i obiektówCalculating database and objects sizes

Następujące zapytanie zwraca rozmiar bazy danych (w megabajtach):The following query returns the size of your database (in megabytes):

-- 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

Następujące zapytanie zwraca rozmiar pojedynczych obiektów (w megabajtach) w bazie danych:The following query returns the size of individual objects (in megabytes) in your database:

-- 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

Monitorowanie połączeńMonitoring connections

Za pomocą widoku sys. dm_exec_connections można pobrać informacje o połączeniach ustanowionych na określonym serwerze i wystąpieniu zarządzanym oraz szczegóły poszczególnych połączeń.You can use the sys.dm_exec_connections view to retrieve information about the connections established to a specific server and managed instance and the details of each connection. Ponadto widok sys. dm_exec_sessions jest przydatny podczas pobierania informacji o wszystkich aktywnych połączeniach użytkowników i zadaniach wewnętrznych.In addition, the sys.dm_exec_sessions view is helpful when retrieving information about all active user connections and internal tasks.

Następujące zapytanie pobiera informacje dotyczące bieżącego połączenia:The following query retrieves information on the current connection:

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;

Uwaga

W przypadku wykonywania widoków sys. dm_exec_requests i sys. dm_exec_sessions, jeśli masz uprawnienia do wyświetlania stanu bazy danych w bazie danych, zobaczysz wszystkie wykonywane sesje w bazie danych. w przeciwnym razie zostanie wyświetlona tylko bieżąca sesja.When executing the sys.dm_exec_requests and sys.dm_exec_sessions views, if you have VIEW DATABASE STATE permission on the database, you see all executing sessions on the database; otherwise, you see only the current session.

Monitoruj użycie zasobówMonitor resource use

Korzystając z SQL Database szczegółowe informacje o wydajności zapytań, można monitorować użycie zasobów Azure SQL Database.You can monitor Azure SQL Database resource usage using SQL Database Query Performance Insight. W przypadku Azure SQL Database i wystąpienia zarządzanego usługi Azure SQL można monitorować przy użyciu magazynu zapytań.For Azure SQL Database and Azure SQL Managed Instance, you can monitor using Query Store.

Możesz również monitorować użycie przy użyciu następujących widoków:You can also monitor usage using these views:

sys. dm_db_resource_statssys.dm_db_resource_stats

W każdej bazie danych można użyć widoku sys. dm_db_resource_stats .You can use the sys.dm_db_resource_stats view in every database. Widok sys. dm_db_resource_stats pokazuje ostatnie dane użycia zasobów względem warstwy usług.The sys.dm_db_resource_stats view shows recent resource use data relative to the service tier. Średnia wartość procentowa dla procesora CPU, operacji we/wy danych, zapisów dziennika i pamięci są rejestrowane co 15 sekund i są przechowywane przez 1 godzinę.Average percentages for CPU, data IO, log writes, and memory are recorded every 15 seconds and are maintained for 1 hour.

Ponieważ ten widok zapewnia bardziej szczegółowy wgląd w użycie zasobów, należy najpierw użyć wykazu sys. dm_db_resource_stats , aby uzyskać aktualną analizę stanu lub Rozwiązywanie problemów.Because this view provides a more granular look at resource use, use sys.dm_db_resource_stats first for any current-state analysis or troubleshooting. Na przykład to zapytanie pokazuje średnie i maksymalne użycie zasobów dla bieżącej bazy danych w ciągu ostatniej godziny:For example, this query shows the average and maximum resource use for the current database over the past hour:

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;  

Inne zapytania można znaleźć w przykładach w tabeli sys. dm_db_resource_stats.For other queries, see the examples in sys.dm_db_resource_stats.

sys. server_resource_statssys.server_resource_stats

Można użyć wykazu sys. server_resource_stats , aby zwrócić użycie procesora CPU, we/wy i dane magazynu dla wystąpienia zarządzanego Azure SQL.You can use sys.server_resource_stats to return CPU usage, IO, and storage data for an Azure SQL Managed Instance. Dane są zbierane i agregowane w ciągu pięciu minut.The data is collected and aggregated within five-minute intervals. Każde 15-sekundowe raportowanie ma jeden wiersz.There is one row for every 15 seconds reporting. Zwrócone dane obejmują użycie procesora CPU, rozmiar magazynu, użycie we/wy i jednostkę SKU wystąpienia zarządzanego.The data returned includes CPU usage, storage size, IO utilization, and managed instance SKU. Dane historyczne są przechowywane przez około 14 dni.Historical data is retained for approximately 14 days.

DECLARE @s datetime;  
DECLARE @e datetime;  
SET @s= DateAdd(d,-7,GetUTCDate());  
SET @e= GETUTCDATE();  
SELECT resource_name, AVG(avg_cpu_percent) AS Average_Compute_Utilization
FROM sys.server_resource_stats
WHERE start_time BETWEEN @s AND @e  
GROUP BY resource_name  
HAVING AVG(avg_cpu_percent) >= 80

sys. resource_statssys.resource_stats

Widok sys. resource_stats w bazie danych Master zawiera dodatkowe informacje, które mogą ułatwić monitorowanie wydajności bazy danych w określonej warstwie usług i rozmiarze obliczeniowym.The sys.resource_stats view in the master database has additional information that can help you monitor the performance of your database at its specific service tier and compute size. Dane są zbierane co 5 minut i są przechowywane przez około 14 dni.The data is collected every 5 minutes and is maintained for approximately 14 days. Ten widok jest przydatny do długoterminowej analizy historycznej, w jaki sposób baza danych używa zasobów.This view is useful for a longer-term historical analysis of how your database uses resources.

Na poniższym wykresie przedstawiono użycie zasobów procesora CPU dla bazy danych w warstwie Premium z wielkością obliczeniową P2 dla każdej godziny w tygodniu.The following graph shows the CPU resource use for a Premium database with the P2 compute size for each hour in a week. Ten wykres zaczyna się w poniedziałek, pokazuje 5 dni roboczych, a następnie pokazuje weekend, gdy jest znacznie mniejszy w aplikacji.This graph starts on a Monday, shows 5 work days, and then shows a weekend, when much less happens on the application.

Użycie zasobów bazy danych

Z danych ta baza danych ma obecnie szczytowe obciążenie procesora CPU znacznie ponad 50% użycia procesora CPU względem rozmiaru obliczeniowego P2 (środku dnia we wtorek).From the data, this database currently has a peak CPU load of just over 50 percent CPU use relative to the P2 compute size (midday on Tuesday). Jeśli procesor jest dominującym czynnikiem w profilu zasobów aplikacji, można zdecydować, że P2 jest odpowiednim rozmiarem obliczeniowym, aby zagwarantować, że obciążenie zawsze mieści się.If CPU is the dominant factor in the application's resource profile, then you might decide that P2 is the right compute size to guarantee that the workload always fits. Jeśli oczekujesz, że aplikacja zostanie powiększona z upływem czasu, dobrym pomysłem jest posiadanie dodatkowego buforu zasobów, dzięki czemu aplikacja nie osiągnie limitu poziomu wydajności.If you expect an application to grow over time, it's a good idea to have an extra resource buffer so that the application doesn't ever reach the performance-level limit. W przypadku zwiększenia rozmiaru obliczeń można zapobiec błędom widocznym dla klienta, które mogą wystąpić, gdy baza danych nie ma wystarczającej mocy, aby efektywnie przetwarzać żądania, szczególnie w środowiskach z uwzględnieniem opóźnień.If you increase the compute size, you can help avoid customer-visible errors that might occur when a database doesn't have enough power to process requests effectively, especially in latency-sensitive environments. Przykładem jest baza danych, która obsługuje aplikację, która maluje strony sieci Web na podstawie wyników wywołań bazy danych.An example is a database that supports an application that paints webpages based on the results of database calls.

Inne typy aplikacji mogą interpretować ten sam wykres inaczej.Other application types might interpret the same graph differently. Na przykład jeśli aplikacja próbuje przetwarzać dane listy płac codziennie i ma ten sam wykres, ten rodzaj modelu "zadanie wsadowe" może być bardziej przydatny w rozmiarze obliczeń P1.For example, if an application tries to process payroll data each day and has the same chart, this kind of "batch job" model might do fine at a P1 compute size. Rozmiar obliczeń P1 ma 100 DTU w porównaniu do 200 DTU w rozmiarze obliczeniowym P2.The P1 compute size has 100 DTUs compared to 200 DTUs at the P2 compute size. Rozmiar obliczeń P1 zapewnia połowę wydajności rozmiaru obliczeniowego P2.The P1 compute size provides half the performance of the P2 compute size. Tak więc 50 procent użycia procesora CPU w P2 równa się 100% użycia procesora CPU w P1.So, 50 percent of CPU use in P2 equals 100 percent CPU use in P1. Jeśli aplikacja nie ma limitów czasu, być może nie ma znaczenia, czy zadanie trwa 2 godziny lub 2,5 godzin, jeśli zostanie zakończone dzisiaj.If the application does not have timeouts, it might not matter if a job takes 2 hours or 2.5 hours to finish, if it gets done today. Aplikacja w tej kategorii prawdopodobnie może korzystać z rozmiaru obliczeń P1.An application in this category probably can use a P1 compute size. Można wykorzystać fakt, że w ciągu dnia istnieją okresy, w których użycie zasobów jest niższe, dzięki czemu każdy "duży szczyt" może zostać przelana do jednego z troughsów w ciągu dnia.You can take advantage of the fact that there are periods of time during the day when resource use is lower, so that any "big peak" might spill over into one of the troughs later in the day. Rozmiar obliczeń P1 może być dobry dla tego rodzaju aplikacji (i oszczędności oszczędności), o ile zadania mogą zakończyć się codziennie.The P1 compute size might be good for that kind of application (and save money), as long as the jobs can finish on time each day.

Aparat bazy danych udostępnia informacje o zasobach dla każdej aktywnej bazy danych w widoku sys. resource_stats bazy danych Master na każdym serwerze.The database engine exposes consumed resource information for each active database in the sys.resource_stats view of the master database in each server. Dane w tabeli są agregowane dla 5-minutowych interwałów.The data in the table is aggregated for 5-minute intervals. W przypadku warstw usług podstawowa, standardowa i Premium dane w tabeli mogą trwać więcej niż 5 minut, więc dane te są bardziej przydatne do analizy historycznej, a nie do analizy w czasie rzeczywistym.With the Basic, Standard, and Premium service tiers, the data can take more than 5 minutes to appear in the table, so this data is more useful for historical analysis rather than near-real-time analysis. Wykonaj zapytanie dotyczące widoku sys. resource_stats , aby zobaczyć ostatnią historię bazy danych i sprawdzić, czy rezerwacja została wybrana, w razie potrzeby podano żądaną wydajność.Query the sys.resource_stats view to see the recent history of a database and to validate whether the reservation you chose delivered the performance you want when needed.

Uwaga

Na Azure SQL Database, musisz nawiązać połączenie z bazą danych Master , aby zbadać sys. resource_stats w poniższych przykładach.On Azure SQL Database, you must be connected to the master database to query sys.resource_stats in the following examples.

Ten przykład pokazuje, jak są udostępniane dane w tym widoku:This example shows you how the data in this view is exposed:

SELECT TOP 10 *
FROM sys.resource_stats
WHERE database_name = 'resource1'
ORDER BY start_time DESC

Widok wykazu sys. resource_stats

W następnym przykładzie pokazano różne sposoby używania widoku wykazu sys. resource_stats , aby uzyskać informacje na temat używania zasobów przez bazę danych:The next example shows you different ways that you can use the sys.resource_stats catalog view to get information about how your database uses resources:

  1. Aby przyjrzeć się zasobom używanym w ostatnim tygodniu dla bazy danych userdb1, możesz uruchomić następujące zapytanie:To look at the past week's resource use for the database userdb1, you can run this query:

    SELECT *
    FROM sys.resource_stats
    WHERE database_name = 'userdb1' AND
        start_time > DATEADD(day, -7, GETDATE())
    ORDER BY start_time DESC;
    
  2. Aby oszacować, w jaki sposób obciążenie jest zgodne z rozmiarem obliczeń, należy przejść do szczegółów poszczególnych aspektów metryk zasobów: procesor, Odczyt, zapis, liczba procesów roboczych i liczba sesji.To evaluate how well your workload fits the compute size, you need to drill down into each aspect of the resource metrics: CPU, reads, writes, number of workers, and number of sessions. Oto poprawione zapytanie przy użyciu wykazu sys. resource_stats , aby zgłosić średnią i maksymalną wartość tych metryk zasobów:Here's a revised query using sys.resource_stats to report the average and maximum values of these resource metrics:

    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 physical data IO use in percent',
        max(avg_data_io_percent) AS 'Maximum physical data IO use 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(max_session_percent) AS 'Average % of sessions',
        max(max_session_percent) AS 'Maximum % of sessions',
        avg(max_worker_percent) AS 'Average % of workers',
        max(max_worker_percent) AS 'Maximum % of workers'
    FROM sys.resource_stats
    WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
    
  3. Dzięki tym informacjom dotyczącym średnich i maksymalnych wartości każdej metryki zasobów można ocenić, w jaki sposób obciążenie mieści się w wybranym rozmiarze.With this information about the average and maximum values of each resource metric, you can assess how well your workload fits into the compute size you chose. Zazwyczaj średnie wartości z wykazu sys. resource_stats zapewniają dobrą linię bazową do użycia względem rozmiaru docelowego.Usually, average values from sys.resource_stats give you a good baseline to use against the target size. Powinna to być podstawowa pomiar.It should be your primary measurement stick. Przykładowo może być używana standardowa warstwa usługi z rozmiarem obliczeń S2.For an example, you might be using the Standard service tier with S2 compute size. Średnie wartości procentowe użycia dla operacji odczytu i zapisu procesora CPU i we/wy są poniżej 40%, średnia liczba procesów roboczych poniżej 50, a średnia liczba sesji jest poniżej 200.The average use percentages for CPU and IO reads and writes are below 40 percent, the average number of workers is below 50, and the average number of sessions is below 200. Obciążenie może być zgodne z rozmiarem obliczeń S1.Your workload might fit into the S1 compute size. Można łatwo sprawdzić, czy baza danych mieści się w limicie procesów roboczych i sesji.It's easy to see whether your database fits in the worker and session limits. Aby sprawdzić, czy baza danych mieści się w mniejszym rozmiarze obliczeniowym w odniesieniu do procesora CPU, odczytów i zapisów, Podziel liczbę jednostek DTU o mniejszym rozmiarze obliczeń przez liczbę jednostek DTU bieżącego rozmiaru obliczeń, a następnie pomnóż wynik przez 100:To see whether a database fits into a lower compute size with regards to CPU, reads, and writes, divide the DTU number of the lower compute size by the DTU number of your current compute size, and then multiply the result by 100:

    S1 DTU / S2 DTU * 100 = 20 / 50 * 100 = 40

    Wynik jest względną różnicą wydajnościową między dwoma wielkościami obliczeniowymi wyrażoną w procentach.The result is the relative performance difference between the two compute sizes in percentage. Jeśli użycie zasobów nie przekracza tej wartości, obciążenie może zmieścić się w mniejszym rozmiarze.If your resource use doesn't exceed this amount, your workload might fit into the lower compute size. Należy jednak przyjrzeć się wszystkim zakresom wartości użycia zasobów i określić procent, jak często obciążenie bazy danych zmieści się w mniejszym rozmiarze.However, you need to look at all ranges of resource use values, and determine, by percentage, how often your database workload would fit into the lower compute size. Następujące zapytanie zwraca procent dopasowania na wymiar zasobu, na podstawie progu 40% obliczonego w tym przykładzie:The following query outputs the fit percentage per resource dimension, based on the threshold of 40 percent that we calculated in this example:

     SELECT
         (COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'CPU Fit Percent',
         (COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'Log Write Fit Percent',
         (COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'Physical Data IO Fit Percent'
     FROM sys.resource_stats
     WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
    

    Na podstawie warstwy usług bazy danych można zdecydować, czy obciążenie mieści się w mniejszym rozmiarze.Based on your database service tier, you can decide whether your workload fits into the lower compute size. Jeśli cel obciążenia bazy danych wynosi 99,9%, a poprzednie zapytanie zwraca wartości większe niż 99,9 procent dla wszystkich trzech wymiarów zasobów, obciążenie prawdopodobnie mieści się w mniejszym rozmiarze.If your database workload objective is 99.9 percent and the preceding query returns values greater than 99.9 percent for all three resource dimensions, your workload likely fits into the lower compute size.

    Poszukiwanie wartości procentowej dopasowania zapewnia również wgląd w to, czy należy przenieść do kolejnego wyższego rozmiaru obliczeniowego, aby osiągnąć cel.Looking at the fit percentage also gives you insight into whether you should move to the next higher compute size to meet your objective. Na przykład userdb1 pokazuje następujące użycie procesora CPU w ubiegłym tygodniu:For example, userdb1 shows the following CPU use for the past week:

    Średni procent procesora CPUAverage CPU percent Maksymalny procent użycia procesora CPUMaximum CPU percent
    24,524.5 100,00100.00

    Średni procesor CPU jest około kwartału limitu rozmiaru obliczeniowego, który może być również dopasowany do rozmiaru obliczeniowego bazy danych.The average CPU is about a quarter of the limit of the compute size, which would fit well into the compute size of the database. Jednak wartość maksymalna pokazuje, że baza danych osiągnie limit rozmiaru obliczeń.But, the maximum value shows that the database reaches the limit of the compute size. Czy chcesz przejść do kolejnego większego rozmiaru obliczeń?Do you need to move to the next higher compute size? Sprawdź, ile razy obciążenie osiągnie 100 procent, a następnie porównaj je z celem obciążenia bazy danych.Look at how many times your workload reaches 100 percent, and then compare it to your database workload objective.

    SELECT
        (COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'CPU fit percent'
        ,(COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'Log write fit percent'
        ,(COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS 'Physical data IO fit percent'
        FROM sys.resource_stats
        WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
    

    Jeśli zapytanie zwróci wartość mniejszą niż 99,9 procent dla dowolnego z trzech wymiarów zasobów, należy rozważyć przeniesienie do następnego wyższego rozmiaru lub użycie technik dostrajania aplikacji w celu zmniejszenia obciążenia bazy danych.If this query returns a value less than 99.9 percent for any of the three resource dimensions, consider either moving to the next higher compute size or use application-tuning techniques to reduce the load on the database.

  4. To ćwiczenie uwzględnia również przewidywany wzrost obciążenia w przyszłości.This exercise also considers your projected workload increase in the future.

W przypadku pul elastycznych można monitorować pojedyncze bazy danych w puli za pomocą metod opisanych w tej sekcji.For elastic pools, you can monitor individual databases in the pool with the techniques described in this section. Można jednak również monitorować pulę jako całość.But you can also monitor the pool as a whole. Informacje na ten temat znajdziesz w artykule Monitor and manage an elastic pool (Monitorowanie puli elastycznej i zarządzanie nią).For information, see Monitor and manage an elastic pool.

Maksymalna liczba równoczesnych żądańMaximum concurrent requests

Aby sprawdzić liczbę równoczesnych żądań, Uruchom to zapytanie Transact-SQL w bazie danych:To see the number of concurrent requests, run this Transact-SQL query on your database:

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

Aby przeanalizować obciążenie SQL Server bazy danych, zmodyfikuj to zapytanie w celu odfiltrowania konkretnej bazy danych, którą chcesz analizować.To analyze the workload of a SQL Server database, modify this query to filter on the specific database you want to analyze. Na przykład jeśli masz lokalną bazę danych o nazwie Moja baza danych, zapytanie Transact-SQL zwraca liczbę równoczesnych żądań w tej bazie danych:For example, if you have an on-premises database named MyDatabase, this Transact-SQL query returns the count of concurrent requests in that database:

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';

Jest to tylko migawka w jednym punkcie w czasie.This is just a snapshot at a single point in time. Aby lepiej zrozumieć obciążenie i współbieżne wymagania dotyczące żądań, należy zebrać wiele próbek w czasie.To get a better understanding of your workload and concurrent request requirements, you'll need to collect many samples over time.

Maksymalna liczba współbieżnych logowańMaximum concurrent logins

Możesz analizować wzorce użytkownika i aplikacji, aby uzyskać pomysł z częstotliwością logowań.You can analyze your user and application patterns to get an idea of the frequency of logins. Możesz również uruchomić rzeczywiste obciążenia w środowisku testowym, aby upewnić się, że nie są to ani inne limity omawiane w tym artykule.You also can run real-world loads in a test environment to make sure that you're not hitting this or other limits we discuss in this article. Nie istnieje pojedyncze zapytanie ani dynamiczny widok zarządzania (DMV), który może wyświetlać współbieżne liczby logowań lub historię.There isn't a single query or dynamic management view (DMV) that can show you concurrent login counts or history.

Jeśli wielu klientów używa tych samych parametrów połączenia, usługa uwierzytelnia każde logowanie.If multiple clients use the same connection string, the service authenticates each login. Jeśli 10 użytkowników jednocześnie nawiąże połączenie z bazą danych przy użyciu tej samej nazwy użytkownika i hasła, zostanie 10 współbieżnych logowań.If 10 users simultaneously connect to a database by using the same username and password, there would be 10 concurrent logins. Ten limit dotyczy tylko czasu trwania logowania i uwierzytelniania.This limit applies only to the duration of the login and authentication. Jeśli ten sam 10 użytkowników łączy się z bazą danych sekwencyjnie, liczba współbieżnych logowań nigdy nie będzie większa niż 1.If the same 10 users connect to the database sequentially, the number of concurrent logins would never be greater than 1.

Uwaga

Obecnie ten limit nie ma zastosowania do baz danych w pulach elastycznych.Currently, this limit does not apply to databases in elastic pools.

Maksymalna liczba sesjiMaximum sessions

Aby wyświetlić liczbę bieżących aktywnych sesji, Uruchom to zapytanie Transact-SQL w bazie danych:To see the number of current active sessions, run this Transact-SQL query on your database:

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

W przypadku analizowania obciążenia SQL Server należy zmodyfikować zapytanie, aby skoncentrować się na określonej bazie danych.If you're analyzing a SQL Server workload, modify the query to focus on a specific database. To zapytanie pomaga określić możliwe potrzeby sesji dla bazy danych, Jeśli rozważasz przechodzenie na platformę Azure.This query helps you determine possible session needs for the database if you are considering moving it to 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'

Ponownie te zapytania zwracają liczbę punktów w czasie.Again, these queries return a point-in-time count. Jeśli zbierasz wiele przykładów z upływem czasu, będziesz mieć najlepszą wiedzę na temat użycia sesji.If you collect multiple samples over time, you'll have the best understanding of your session use.

Możesz uzyskać historyczne statystyki dotyczące sesji, badając widok sys. resource_stats i przeglądając kolumnę active_session_count .You can get historical statistics on sessions by querying the sys.resource_stats view and reviewing the active_session_count column.

Monitorowanie wydajności zapytańMonitoring query performance

Zapytania powolne lub długotrwałe mogą zużywać znaczne zasoby systemowe.Slow or long running queries can consume significant system resources. W tej sekcji przedstawiono sposób korzystania z dynamicznych widoków zarządzania w celu wykrywania kilku typowych problemów z wydajnością zapytań.This section demonstrates how to use dynamic management views to detect a few common query performance problems.

Znajdowanie pierwszych N zapytańFinding top N queries

Poniższy przykład zwraca informacje o pięciu pierwszych zapytania sklasyfikowanych według średniego czasu procesora CPU.The following example returns information about the top five queries ranked by average CPU time. Ten przykład agreguje zapytania według ich wartości skrótu zapytania, tak aby logicznie równoważne zapytania były pogrupowane według ich łącznego zużycia zasobów.This example aggregates the queries according to their query hash, so that logically equivalent queries are grouped by their cumulative resource consumption.

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;

Monitorowanie zablokowanych zapytańMonitoring blocked queries

Wykonywanie wolnych lub długotrwałych zapytań może współtworzyć nadmierne zużycie zasobów i być konsekwencją zablokowanych zapytań.Slow or long-running queries can contribute to excessive resource consumption and be the consequence of blocked queries. Przyczyną blokowania może być słaba konstrukcja aplikacji, złe plany zapytań, brak przydatnych indeksów i tak dalej.The cause of the blocking can be poor application design, bad query plans, the lack of useful indexes, and so on. Możesz użyć widoku sys. dm_tran_locks, aby uzyskać informacje o bieżącym działaniu blokowania w bazie danych.You can use the sys.dm_tran_locks view to get information about the current locking activity in database. Na przykład kod, zobacz sys. dm_tran_locks (Transact-SQL).For example code, see sys.dm_tran_locks (Transact-SQL).

Monitorowanie planów zapytańMonitoring query plans

Nieefektywny plan zapytania może również zwiększyć użycie procesora CPU.An inefficient query plan also may increase CPU consumption. Poniższy przykład używa widoku sys. dm_exec_query_stats , aby określić, które zapytanie używa najbardziej SKUMULOWANEGO procesora CPU.The following example uses the sys.dm_exec_query_stats view to determine which query uses the most cumulative CPU.

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;

Zobacz takżeSee also

Wprowadzenie do Azure SQL Database i wystąpienia zarządzanego usługi Azure SQLIntroduction to Azure SQL Database and Azure SQL Managed Instance