مراقبة قاعدة بيانات Microsoft Azure SQL وأداء المثيل المُدار من Azure SQL باستخدام طرق عرض الإدارة الديناميكية

ينطبق على: Azure SQL Database Azure SQL Managed Instance

تتيح قاعدة بيانات Microsoft Azure SQL ومثيل Azure SQL المُدار مجموعة فرعية من طرق عرض الإدارة الديناميكية لتشخيص مشاكل الأداء، والتي قد تكون ناجمة عن الاستعلامات المحظورة أو طويلة المدى، واختناقات الموارد، وخطط الاستعلام الضعيفة، وما إلى ذلك. توفر هذه المقالة معلومات حول كيفية اكتشاف مشاكل الأداء الشائعة باستخدام طرق عرض الإدارة الديناميكية.

تدعم قاعدة بيانات Microsoft Azure SQL ومثيل Azure SQL المُدار جزئيًا ثلاث فئات من طرق عرض الإدارة الديناميكية:

  • طرق عرض الإدارة الديناميكية المتعلقة بقاعدة البيانات.
  • وجهات نظر الإدارة الديناميكية المتعلقة بالتنفيذ.
  • طرق عرض الإدارة الديناميكية المتعلقة بالمعاملات.

للحصول على معلومات تفصيلية حول طرق عرض الإدارة الديناميكية راجع طرق عرض ووظائف الإدارة الديناميكية (Transact-SQL).

المراقبة باستخدام SQL Insights (إصدار أولي)

Azure Monitor SQL Insights (إصدار أولي) هي أداة لمراقبة المثيلات المدارة من Azure SQL وقواعد البيانات في Azure SQL Database ومثيلات SQL Server في Azure SQL VMs. تستخدم هذه الخدمة وكيلاً بعيداً لالتقاط البيانات من طرق عرض الإدارة الديناميكية (DMVs) وتوجيه البيانات إلى Azure Log Analytics، حيث يمكن مراقبتها وتحليلها. يمكنك عرض هذه البيانات من Azure Monitor في طرق العرض المتوفرة، أو الوصول إلى بيانات السجل مباشرة لتشغيل الاستعلامات وتحليل الاتجاهات. لبدء استخدام Azure Monitor SQL Insights (إصدار أولي)، راجع تمكين تفاصيل SQL (إصدار أولي).

الأذونات

في قاعدة بيانات Azure SQL؛ يتطلب الاستعلام عن طريقة عرض الإدارة الديناميكية أذونات عرض حالة قاعدة البيانات. يعرض الإذن حالة قاعدة البيانات معلومات حول كافة الكائنات الموجودة في قاعدة البيانات الحالية. لمنح إذن عرض حالة قاعدة البيانات لمستخدم قاعدة بيانات معين، قم بتشغيل الاستعلام التالي:

GRANT VIEW DATABASE STATE TO database_user;

في Azure SQL Managed Instance؛ يتطلب الاستعلام عن طريقة عرض الإدارة الديناميكية أذونات VIEW SERVER STATE. لمزيد من المعلومات راجع طرق عرض الإدارة الديناميكية للنظام.

في مثيل SQL Server وفي مثيل Azure SQL المُدار؛ ترجع طرق عرض الإدارة الديناميكية معلومات حالة الخادم. في قاعدة بيانات Azure SQL؛ يقومون بإرجاع معلومات تتعلق بقاعدة البيانات المنطقية الحالية فقط.

تحتوي هذه المقالة على مجموعة من استعلامات DMV التي يمكنك تنفيذها باستخدام SQL Server Management Studio أوAzure Data Studio لاكتشاف الأنواع التالية من مشكلات أداء الاستعلام:

التعرف على مشكلات أداء وحدة المعالجة المركزية

إذا كان استهلاك وحدة المعالجة المركزية أعلى من 80٪ لفترات طويلة؛ ففكر في خطوات استكشاف الأخطاء وإصلاحها التالية:

تحدث مشكلة وحدة المعالجة المركزية الآن

إذا حدثت مشكلة في الوقت الحالي فهناك سيناريوهان محتملان:

العديد من الاستعلامات الفردية التي تستهلك -بشكل تراكمي- وحدة معالجة مركزية عالية

استخدم الاستعلام التالي لتحديد أهم تجزئات الاستعلام:

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;

لا تزال الاستعلامات طويلة الأمد التي تستهلك وحدة المعالجة المركزية قيد التشغيل

استخدم الاستعلام التالي لتحديد هذه الاستعلامات:

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

حدثت مشكلة وحدة المعالجة المركزية في الماضي

إذا حدثت المشكلة في الماضي وتريد إجراء تحليل للسبب الجذري فاستخدم Query Store. يمكن للمستخدمين الذين لديهم حق الوصول إلى قاعدة البيانات استخدام T-SQL للاستعلام عن بيانات Query Store. تستخدم التكوينات الافتراضية لمتجر الاستعلام دقة تبلغ ساعة واحدة. استخدم الاستعلام التالي لإلقاء نظرة على نشاط الاستعلامات التي تستهلك الكثير من وحدة المعالجة المركزية. يعرض هذا الاستعلام أهم 15 استعلامًا عن استهلاك وحدة المعالجة المركزية. تذكر تغيير 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;

بمجرد تحديد الاستعلامات الإشكالية؛ حان الوقت لضبط هذه الاستعلامات لتقليل استخدام وحدة المعالجة المركزية. إذا لم يكن لديك الوقت لضبط الاستعلامات فيمكنك أيضًا اختيار ترقية SLO لقاعدة البيانات للتغلب على المشكلة.

بالنسبة لمستخدمي Azure SQL Database، تعرف على المزيد حول التعامل مع مشاكل أداء وحدة المعالجة المركزية في تشخيص واستكشاف أخطاء وحدة المعالجة المركزية عالية المستوى في Azure SQL Database وإصلاحها

التعرف على مشكلات أداء IO

عند تحديد مشكلات أداء الإدخال / الإخراج فإن أهم أنواع الانتظار المرتبطة بمشكلات الإدخال / الإخراج هي:

  • PAGEIOLATCH_*

    لمشكلات إدخال / إخراج ملف البيانات (بما في ذلك PAGEIOLATCH_SH، PAGEIOLATCH_EX، PAGEIOLATCH_UP). إذا كان اسم نوع الانتظار يحتوي على IO فهذا يشير إلى وجود مشكلة IO. إذا لم يكن هناك IO في اسم انتظار مزلاج الصفحة فهذا يشير إلى نوع مختلف من المشكلات (على سبيل المثال، تنازع tempdb).

  • WRITE_LOG

    لقضايا إدخال / إخراج سجل المعاملات.

إذا كانت مشكلة الإدخال / الإخراج تحدث الآن

استخدم sys.dm_exec_requests أو sys.dm_os_waiting_tasks لمشاهدة wait_typeandwait_time.

تحديد البيانات وتسجيل استخدام الإدخال / الإخراج

استخدم الاستعلام التالي لتحديد البيانات وتسجيل استخدام الإدخال / الإخراج. إذا كانت البيانات أو سجل الإدخال / الإخراج أعلى من 80٪، فهذا يعني أن المستخدمين قد استخدموا الإدخال / الإخراج المتاح لطبقة خدمة قاعدة بيانات SQL.

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

إذا تم الوصول إلى حد الإدخال / الإخراج، فلديك خياران:

  • الخيار 1: ترقية حجم الحساب أو مستوى الخدمة
  • الخيار 2: تحديد وضبط الاستعلامات التي تستهلك معظم عمليات الإدخال والإخراج.

بالنسبة للخيار 2؛ يمكنك استخدام الاستعلام التالي في Query Store لـ IO المرتبط بالمخزن المؤقت لعرض آخر ساعتين من النشاط المتعقب:

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

عرض إجمالي سجل الإدخال والإخراج في انتظار WRITELOG

إذا كان نوع الانتظار هو WRITELOG فاستخدم الاستعلام التالي لعرض إجمالي سجل الإدخال والإخراج حسب العبارة:

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

تحديد مشكلات الأداء tempdb

عند تحديد مشكلات أداء IO فإن أهم أنواع الانتظار المرتبطة بـ tempdbالمشكلات هيPAGELATCH_* (وليس PAGEIOLATCH_*). ومع ذلك؛ لا تعني فترات الانتظار PAGELATCH_*دائمًا أن لديكtempdb نزاع. قد يعني هذا الانتظار أيضًا أن لديك تنازعًا في صفحة بيانات كائن المستخدم بسبب الطلبات المتزامنة التي تستهدف صفحة البيانات نفسها. لتأكيد الخلاف tempdb بشكل أكبر؛ استخدم sys.dm_exec_requests لتأكيد أن قيمة wait_resource تبدأ بـ 2:x:yحيث 2 هيtempdb معرف قاعدة البيانات، وxهو معرف الملف، و هوy معرف الصفحة.

بالنسبة للتنازع في tempdb، تتمثل إحدى الطرق الشائعة في تقليل أو إعادة كتابة رمز التطبيق الذي يعتمد على tempdb. تشمل مجالات الاستخدام tempdb الشائعة ما يلي:

  • الجداول المؤقتة
  • متغيرات الجدول
  • معلمات الجدول
  • استخدام متجر الإصدار (المرتبط بالمعاملات طويلة الأمد)
  • الاستعلامات التي تحتوي على خطط استعلام تستخدم الفرز ووصلات التجزئة والملفات المؤقتة

أهم الاستعلامات التي تستخدم متغيرات الجدول والجداول المؤقتة

استخدم الاستعلام التالي لتحديد أهم الاستعلامات التي تستخدم متغيرات الجدول والجداول المؤقتة:

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;

تحديد المعاملات طويلة الأمد

استخدم الاستعلام التالي لتحديد المعاملات طويلة الأمد. تمنع المعاملات التي يتم تشغيلها لفترة طويلة تنظيف مخزن الإصدار.

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;

التعرف على مشكلات أداء منح الانتظار

إذا كان أفضل نوع انتظار لديك هو RESOURCE_SEMAHPORE ولم تكن لديك مشكلة كبيرة في استخدام وحدة المعالجة المركزية؛ فقد تواجه مشكلة في انتظار منح الذاكرة.

حدد ما إذا كان انتظار RESOURCE_SEMAHPORE يمثل انتظارًا رئيسيًا

استخدم الاستعلام التالي لتحديد ما إذا كان انتظار RESOURCE_SEMAHPORE هو انتظار رئيسي

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;

تحديد العبارات التي تستهلك ذاكرة عالية

استخدم الاستعلام التالي لتحديد العبارات التي تستهلك ذاكرة كبيرة:

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;

إذا واجهت أخطاء نفاد الذاكرة في Azure SQL Database، فراجع sys.dm_os_out_of_memory_events.

حدد أفضل 10 منح للذاكرة النشطة

استخدم الاستعلام التالي لتحديد أفضل 10 منح للذاكرة النشطة:

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;

حساب قاعدة البيانات وأحجام الكائنات

يعرض الاستعلام التالي حجم قاعدة البيانات الخاصة بك (بالميغابايت):

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

يعرض الاستعلام التالي حجم العناصر الفردية (بالميغابايت) في قاعدة البيانات الخاصة بك:

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

مراقبة الاتصالات

يمكنك استخدام طريقة العرض sys.dm_exec_connections لاسترداد معلومات حول الاتصالات التي تم إنشاؤها إلى خادم معين ومثيل مُدار وتفاصيل كل اتصال. بالإضافة إلى ذلك؛ فإن طريقة العرض sys.dm_exec_sessions مفيدة عند استرداد المعلومات حول جميع اتصالات المستخدم النشطة والمهام الداخلية.

يقوم الاستعلام التالي باسترداد معلومات عن الاتصال الحالي:

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;

ملاحظة

عند تنفيذ طرق عرض sys.dm_exec_requests و sys.dm_exec_sessions views؛ إذا كان لديك إذن VIEW DATABASE STATE في قاعدة البيانات فسترى جميع جلسات التنفيذ في قاعدة البيانات؛ وإلا سترى الجلسة الحالية فقط.

مراقبة استخدام الموارد

يمكنك مراقبة استخدام موارد قاعدة بيانات Azure SQL باستخدام مؤشرات أداء استعلام قاعدة بيانات SQL. بالنسبة إلى قاعدة بيانات Azure SQL ومثيل Azure SQL المُدار يمكنك المراقبة باستخدام Query Store.

يمكنك أيضًا مراقبة الاستخدام باستخدام طرق العرض التالية:

sys.dm_db_resource_stats

يمكنك استخدام طريقة العرض sys.dm_db_resource_stats في كل قاعدة بيانات. تُظهر طريقة العرض sys.dm_db_resource_stats بيانات استخدام الموارد الحديثة ذات الصلة بمستوى الخدمة. يتم تسجيل متوسط ​​النسب المئوية لوحدة المعالجة المركزية والبيانات IO وعمليات الكتابة في السجل والذاكرة كل 15 ثانية ويتم الاحتفاظ بها لمدة ساعة واحدة.

نظرًا لأن طريقة العرض هذه توفر نظرة أكثر تفصيلاً على استخدام الموارد، استخدم sys.dm_db_resource_stats أولاً لأي تحليل للحالة الحالية أو لتحرّي الخلل وإصلاحه. على سبيل المثال؛ يعرض هذا الاستعلام متوسط ​​والحد الأقصى لاستخدام الموارد لقاعدة البيانات الحالية على مدار الساعة الماضية:

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;  

لطلبات البحث الأخرى؛ راجع الأمثلة في sys.dm_db_resource_stats.

sys.server_resource_stats

يمكنك استخدام sys.server_resource_stats لإرجاع بيانات استخدام وحدة المعالجة المركزية، وإدخال البيانات، والتخزين لمثيل مُدار من Azure SQL. يتم جمع البيانات وتجميعها في فواصل زمنية مدتها خمس دقائق. يوجد صف واحد لكل 15 ثانية من التقارير. تتضمن البيانات التي تم إرجاعها استخدام وحدة المعالجة المركزية، وحجم التخزين، واستخدام الإدخال / الإخراج، وSKU للمثيل المُدار. يتم الاحتفاظ بالبيانات التاريخية لمدة 14 يومًا تقريبًا.

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_stats

تحتوي طريقة العرض sys.resource_stats في قاعدة البيانات master على معلومات إضافية يمكن أن تساعدك في مراقبة أداء قاعدة البيانات في طبقة الخدمة المحددة وحجم الحساب. يتم جمع البيانات كل 5 دقائق ويتم الاحتفاظ بها لمدة 14 يومًا تقريبًا. طريقة العرض هذه مفيدة للتحليل التاريخي الطويل المدى لكيفية استخدام قاعدة البيانات للموارد.

يوضح الرسم البياني التالي استخدام موارد وحدة المعالجة المركزية لقاعدة بيانات Premium مع حجم حساب P2 لكل ساعة في الأسبوع. يبدأ هذا الرسم البياني يوم الاثنين ويعرض خمسة أيام عمل، ثم يعرض عطلة نهاية الأسبوع عندما يحدث القليل في التطبيق.

Database resource use

من البيانات: تحتوي قاعدة البيانات هذه حاليًا على أقصى حمل لوحدة المعالجة المركزية يزيد قليلاً عن 50 بالمائة من استخدام وحدة المعالجة المركزية بالنسبة لحجم حساب P2 (منتصف النهار يوم الثلاثاء). إذا كانت وحدة المعالجة المركزية (CPU) هي العامل المهيمن في ملف تعريف موارد التطبيق؛ فقد تقرر أن P2 هو حجم الحوسبة الصحيح لضمان ملاءمة حمولة العمل دائمًا. إذا كنت تتوقع نمو أحد التطبيقات بمرور الوقت فمن الجيد أن يكون لديك مخزن مؤقت إضافي للموارد؛ بحيث لا يصل التطبيق أبدًا إلى حد مستوى الأداء. إذا قمت بزيادة حجم الحوسبة يمكنك المساعدة في تجنب الأخطاء المرئية للعميل، والتي قد تحدث عندما لا تمتلك قاعدة البيانات القوة الكافية لمعالجة الطلبات بشكل فعال؛ خاصة في البيئات الحساسة لزمن الانتقال. مثال على ذلك هو قاعدة البيانات التي تدعم تطبيقًا يرسم صفحات الويب بناءً على نتائج استدعاءات قاعدة البيانات.

قد تفسر أنواع التطبيقات الأخرى نفس الرسم البياني بشكل مختلف. على سبيل المثال؛ إذا حاول أحد التطبيقات معالجة بيانات كشوف المرتبات كل يوم ولديه نفس الرسم البياني فقد يعمل هذا النوع من نموذج "الوظيفة المجمعة" بشكل جيد عند حجم حساب P1. يحتوي حجم حساب P1 على 100 DTU مقارنة بـ 200 DTU في حجم حساب P2. يوفر حجم حساب P1 نصف أداء حجم حساب P2. لذا؛ فإن 50 بالمائة من استخدام وحدة المعالجة المركزية في P2 يساوي استخدام وحدة المعالجة المركزية بنسبة 100 بالمائة في P1. إذا كان التطبيق لا يحتوي على مهلات فقد لا يهم ما إذا كانت المهمة تستغرق ساعتين أو ساعتين ونصف حتى تنتهي؛ إذا تم إنجازها اليوم. ربما يمكن لتطبيق في هذه الفئة استخدام حجم حساب P1. يمكنك الاستفادة من حقيقة أن هناك فترات من الوقت خلال اليوم يكون فيها استخدام الموارد أقل، وبالتالي فإن أي "ذروة كبيرة" قد تمتد إلى أحد القيعان في وقت لاحق من اليوم. قد يكون حجم حساب P1 جيدًا لهذا النوع من التطبيقات (ويوفر المال)؛ طالما أن المهام يمكن أن تنتهي في الوقت المحدد كل يوم.

يعرض محرك قاعدة البيانات معلومات الموارد المستهلكة لكل قاعدة بيانات نشطة في طريقة عرض sys.resource_stats لقاعدة البيانات master في كل خادم. يتم تجميع البيانات الواردة في الجدول لفترات زمنية مدتها 5 دقائق. باستخدام مستويات الخدمة الأساسية والقياسية والمتميزة يمكن أن تستغرق البيانات أكثر من 5 دقائق لتظهر في الجدول، لذلك تكون هذه البيانات أكثر فائدة للتحليل التاريخي بدلاً من التحليل شبه الحقيقي. استعلم عن طريقة العرض sys.resource_stats للاطلاع على السجل الأخير لقاعدة البيانات، وللتحقق مما إذا كان الحجز الذي اخترته قد حقق الأداء الذي تريده عند الحاجة.

ملاحظة

في قاعدة بيانات Azure SQL يجب أن تكون متصلاً بقاعدة البيانات master للاستعلام عن sys.resource_stats في الأمثلة التالية.

يوضح لك هذا المثال كيفية عرض البيانات في هذا الملف الشخصي:

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

The sys.resource_stats catalog view

يوضح لك المثال التالي طرقًا مختلفة يمكنك من خلالها استخدام عرض الكتالوج sys.resource_stats للحصول على معلومات حول كيفية استخدام قاعدة البيانات للموارد:

  1. لإلقاء نظرة على استخدام موارد الأسبوع الماضي لقاعدة البيانات userdb1؛ يمكنك تشغيل هذا الاستعلام:

    SELECT *
    FROM sys.resource_stats
    WHERE database_name = 'userdb1' AND
        start_time > DATEADD(day, -7, GETDATE())
    ORDER BY start_time DESC;
    
  2. لتقييم مدى ملاءمة حمولة العمل لحجم الحوسبة تحتاج إلى التعمق في كل جانب من جوانب مقاييس الموارد: وحدة المعالجة المركزية، والقراءة، والكتابة، وعدد العمال، وعدد الجلسات. فيما يلي استعلام تمت مراجعته باستخدام sys.resource_stats للإبلاغ عن القيم المتوسطة والحد الأقصى لمقاييس الموارد هذه:

    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. باستخدام هذه المعلومات حول القيم المتوسطة والحد الأقصى لكل مقياس مورد؛ يمكنك تقييم مدى ملاءمة حمولة العمل لحجم الحساب الذي اخترته. عادةً ما يمنحك متوسط ​​القيم من sys.resource_stats أساسًا جيدًا لاستخدامه مقابل الحجم المستهدف. يجب أن تكون عصا القياس الأساسية الخاصة بك. على سبيل المثال؛ قد تستخدم طبقة الخدمة القياسية مع حجم حساب S2. متوسط ​​نسب الاستخدام لوحدة المعالجة المركزية (CPU) وIO (عمليات القراءة والكتابة) أقل من 40 بالمائة، ومتوسط ​​عدد العمال أقل من 50، ومتوسط ​​عدد الجلسات أقل من 200. قد يتناسب حجم العمل مع حجم حساب S1. من السهل معرفة ما إذا كانت قاعدة البيانات الخاصة بك تتناسب مع حدود العامل وجلسة العمل. لمعرفة ما إذا كانت قاعدة البيانات تتناسب مع حجم حساب أقل فيما يتعلق بوحدة المعالجة المركزية، والقراءة والكتابة؛ قسّم رقم DTU لحجم الحوسبة الأقل على رقم DTU لحجم الحساب الحالي، ثم اضرب النتيجة في 100:

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

    والنتيجة هي فرق الأداء النسبي بين حجمي الحوسبة بالنسبة المئوية. إذا لم يتجاوز استخدامك للمورد هذا المقدار فقد يتناسب حجم العمل مع حجم الحوسبة الأقل. ومع ذلك؛ تحتاج إلى إلقاء نظرة على جميع نطاقات قيم استخدام الموارد، وتحدي -بالنسبة المئوية- عدد المرات التي يتناسب فيها حمل عمل قاعدة البيانات مع حجم الحوسبة الأقل. يُخرج الاستعلام التالي النسبة المئوية الملائمة لكل بُعد مورد؛ بناءً على عتبة 40 بالمائة التي حسبناها في هذا المثال:

     SELECT
         100*((COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)) AS 'CPU Fit Percent',
         100*((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',
         100*((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 = 'sample' AND start_time > DATEADD(day, -7, GETDATE());
    

    استنادًا إلى طبقة خدمة قاعدة البيانات الخاصة بك؛ يمكنك تحديد ما إذا كان حمل العمل الخاص بك يتناسب مع حجم الحوسبة الأقل. إذا كان هدف حمل عمل قاعدة البيانات لديك هو 99.9 في المائة وكان الاستعلام السابق يُرجع قيمًا أكبر من 99.9 في المائة لجميع أبعاد الموارد الثلاثة؛ فمن المحتمل أن يتناسب حمل العمل مع حجم الحوسبة الأقل.

    يمنحك النظر إلى النسبة المئوية الملائمة أيضًا نظرة ثاقبة عما إذا كان يجب عليك الانتقال إلى حجم الحوسبة الأعلى التالي لتحقيق هدفك. على سبيل المثال؛ يعرض userdb1 استخدام وحدة المعالجة المركزية التالية للأسبوع الماضي:

    متوسط ​​نسبة CPU أقصى وحدة المعالجة المركزية في المئة
    24.5 100.00

    يبلغ متوسط ​​وحدة المعالجة المركزية حوالي ربع الحد الأقصى لحجم الحوسبة، والذي يتناسب جيدًا مع حجم الحوسبة لقاعدة البيانات. لكن القيمة القصوى توضح أن قاعدة البيانات تصل إلى الحد الأقصى لحجم الحساب. هل تحتاج إلى الانتقال إلى حجم الحوسبة الأعلى التالي؟ انظر إلى عدد المرات التي يصل فيها حمولة العمل إلى 100 بالمائة، ثم قارنه مع هدف حجم عمل قاعدة البيانات.

     SELECT
         100*((COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)) AS 'CPU Fit Percent',
         100*((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',
         100*((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 = 'sample' AND start_time > DATEADD(day, -7, GETDATE());
    

    إذا قام هذا الاستعلام بإرجاع قيمة أقل من 99.9 في المائة لأي من أبعاد الموارد الثلاثة؛ ففكر إما في الانتقال إلى حجم الحوسبة الأعلى التالي أو استخدام تقنيات ضبط التطبيق لتقليل الحمل على قاعدة البيانات.

  4. يأخذ هذا التمرين أيضًا في الاعتبار الزيادة المتوقعة في حمولة العمل في المستقبل.

بالنسبة للتجمعات المرنة؛ يمكنك مراقبة قواعد البيانات الفردية في التجمع باستخدام الأساليب الموضحة في هذا القسم. ولكن يمكنك أيضًا مراقبة المسبح ككل. للحصول على معلومات راجع مراقبة وإدارة البركة المرنة.

الحد الأقصى من الطلبات المتزامنة

لمعرفة عدد الطلبات المتزامنة: قم بتشغيل استعلام Transact-SQL هذا في قاعدة البيانات الخاصة بك:

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

لتحليل حمولة العمل في قاعدة بيانات SQL Server قم بتعديل هذا الاستعلام للتصفية على قاعدة البيانات المحددة التي تريد تحليلها. على سبيل المثال؛ إذا كانت لديك قاعدة بيانات محلية تسمى MyDatabase فسيعرض استعلام Transact-SQL هذا عدد الطلبات المتزامنة في قاعدة البيانات هذه:

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

هذه مجرد لقطة في وقت واحد. للحصول على فهم أفضل لحمولة العمل الخاص بك ومتطلبات الطلبات المتزامنة؛ ستحتاج إلى جمع العديد من العينات بمرور الوقت.

الحد الأقصى لعمليات تسجيل الدخول المتزامنة

يمكنك تحليل أنماط المستخدم والتطبيق للحصول على فكرة عن تكرار تسجيلات الدخول. يمكنك أيضًا تشغيل أحمال حقيقية في بيئة اختبار للتأكد من أنك لا تصل إلى هذه الحدود أو غيرها من القيود التي نناقشها في هذه المقالة. لا يوجد استعلام واحد أو عرض إدارة ديناميكي (DMV) يمكنه إظهار عدد مرات تسجيل الدخول المتزامنة أو سجلها.

إذا كان العديد من العملاء يستخدمون نفس سلسلة الاتصال فإن الخدمة تصادق على كل تسجيل دخول. إذا قام 10 مستخدمين بالاتصال بقاعدة بيانات في وقت واحد باستخدام نفس اسم المستخدم وكلمة المر؛ ، فسيكون هناك 10 عمليات تسجيل دخول متزامنة. ينطبق هذا الحد فقط على مدة تسجيل الدخول والمصادقة. إذا قام نفس المستخدمين العشرة بالاتصال بقاعدة البيانات بشكل تسلسلي، فلن يكون عدد عمليات تسجيل الدخول المتزامنة أكبر من 1.

ملاحظة

حاليًا؛ لا ينطبق هذا الحد على قواعد البيانات الموجودة في التجمعات المرنة.

الجلسات القصوى

لمعرفة عدد الجلسات النشطة الحالية: قم بتشغيل استعلام Transact-SQL هذا في قاعدة البيانات الخاصة بك:

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

إذا كنت تقوم بتحليل عبء عمل SQL Server؛ فقم بتعديل الاستعلام للتركيز على قاعدة بيانات معينة. يساعدك هذا الاستعلام في تحديد احتياجات الجلسة المحتملة لقاعدة البيانات إذا كنت تفكر في نقلها إلى 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';

مرة أخرى؛ تُرجع هذه الاستعلامات عدد النقاط الزمنية. إذا قمت بجمع عينات متعددة بمرور الوقت فسيكون لديك فهم أفضل لاستخدام الجلسة الخاصة بك.

يمكنك الحصول على الإحصائيات السابقة للجلسات عن طريق الاستعلام عن sys.resource_stats عرض ومراجعة عمود active_session_count.

مراقبة أداء الاستعلام

يمكن أن تستهلك الاستعلامات التي يتم تشغيلها ببطء أو طويلاً موارد كبيرة للنظام. يوضح هذا القسم كيفية استخدام طرق عرض الإدارة الديناميكية لاكتشاف بعض مشكلات أداء الاستعلام الشائعة.

البحث عن أهم الاستعلامات N

يعرض المثال التالي معلومات حول أهم خمسة استعلامات مرتبة حسب متوسط ​​وقت وحدة المعالجة المركزية. يقوم هذا المثال بتجميع الاستعلامات وفقًا لتجزئة الاستعلام الخاصة بها، بحيث يتم تجميع الاستعلامات المكافئة منطقيًا حسب استهلاك الموارد التراكمي.

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;

مراقبة الاستعلامات المحظورة

يمكن أن تساهم الاستعلامات البطيئة أو طويلة المدى في الاستهلاك المفرط للموارد وتكون نتيجة للاستعلامات المحظورة. يمكن أن يكون سبب الحظر ضعف تصميم التطبيق، وخطط الاستعلام السيئة، ونقص الفهارس المفيدة، وما إلى ذلك. يمكنك استخدام طريقة العرض sys.dm_tran_locks للحصول على معلومات حول نشاط القفل الحالي في قاعدة البيانات. على سبيل المثال التعليمات البرمجية؛ راجع sys.dm_tran_locks (Transact-SQL). لمزيد من المعلومات حول استكشاف أخطاء الحظر وإصلاحها راجع فهم مشكلات حظر Azure SQL وحلها.

مراقبة حالات التوقف التام

في بعض الحالات، قد يؤدي استعلامان أو أكثر إلى منع أحدهما الآخر، مما يؤدي إلى توقف تام.

يمكنك إنشاء Extended Events لتتبع حدث قاعدة بيانات في Azure SQL Database لالتقاط أحداث حالة توقف تام، ثم البحث عن الاستعلامات ذات الصلة وخطط التنفيذ الخاصة بها في مخزن الاستعلام. تعرف على المزيد في تحليل ومنع حالات التوقف التام في Azure SQL Database.

بالنسبة إلى مثيل Azure SQL المُدار، راجع حالات التوقف التام في تأمين العمليات ودليل تعيين إصدار الصف.

مراقبة خطط الاستعلام

قد تؤدي خطة الاستعلام غير الفعالة أيضًا إلى زيادة استهلاك وحدة المعالجة المركزية. يستخدم المثال التالي طريقة العرض sys.dm_exec_query_stats لتحديد الاستعلام الذي يستخدم وحدة المعالجة المركزية الأكثر تراكمًا.

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;

الخطوات التالية