Teljesítmény monitorozása dinamikus felügyeleti nézetekkel

A következőkre vonatkozik:Azure SQL DatabaseSQL Database a Fabricben

A dinamikus felügyeleti nézetek (DMV-k) lekérdezéséhez Transact-SQL (T-SQL) segítségével figyelheti a számítási feladatok teljesítményét, és diagnosztizálhatja a teljesítményproblémákat, amelyeket blokkolt vagy hosszan futó lekérdezések, erőforrás szűk keresztmetszetek, optimálisnál rosszabb lekérdezési tervek és egyebek okozhatnak.

Grafikus lekérdezési erőforrás monitorozásához használja a Lekérdezéstár.

Tipp

Fontolja meg automatikus adatbázis-finomhangolási a lekérdezési teljesítmény automatikus javítása érdekében.

Erőforrás-használat figyelése

Az erőforrás-használatot az adatbázis szintjén az alábbi DMV-k használatával monitorozhatja.

sys.dm_db_resource_stats

Mivel ez a nézet részletes erőforrás-használati adatokat biztosít, először használja a sys.dm_db_resource_stats az aktuális állapotelemzéshez vagy hibaelhárításhoz. Ez a lekérdezés például az aktuális adatbázis átlagos és maximális erőforrás-használatát mutatja az elmúlt egy órában:

SELECT DB_NAME() AS database_name,
       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',
       MAX(max_worker_percent) AS 'Maximum worker use in percent'
FROM sys.dm_db_resource_stats;

A sys.dm_db_resource_stats nézet a számítási méret korlátaihoz viszonyított legutóbbi erőforrás-használati adatokat jeleníti meg. A cpu, az adatok I/O-értéke, a naplóírások, a feldolgozói szálak és a memóriahasználat százalékos aránya a korlát felé 15 másodpercenként lesz rögzítve, és körülbelül egy óráig tartható fenn.

Ha további minta lekérdezésekre van szüksége, lásd a sys.dm_db_resource_statspéldákat.

sys.resource_stats

A adatbázis master nézete további információkkal rendelkezik, amelyek segíthetnek az adatbázis teljesítményének monitorozásában az adott szolgáltatási szinten és számítási méretben. Az adatokat 5 percenként gyűjtjük, és körülbelül 14 napig tartjuk karban. Ez a nézet hasznos lehet az adatbázis erőforrásainak hosszabb távú előzményelemzéséhez.

Az alábbi grafikon egy prémium szintű adatbázis processzorerőforrás-használatát mutatja be egy hét minden órájában p2 számítási mérettel. Ez a grafikon hétfőn kezdődik, öt munkanapot jelenít meg, majd egy hétvégét jelenít meg, amikor sokkal kevesebb történik az alkalmazásban.

Képernyőkép az adatbázis-erőforrások használatáról készült mintadiagramról.

Az adatok alapján ez az adatbázis jelenleg a P2 számítási mérethez képest (kedd délben) valamivel több mint 50 százalékos processzorhasználati csúcsterheléssel rendelkezik. Ha a CPU az alkalmazás erőforrásprofiljának domináns tényezője, akkor dönthet úgy, hogy a P2 a megfelelő számítási méret, hogy a számítási feladat mindig illeszkedjen. Ha azt várja, hogy egy alkalmazás idővel növekedni fog, érdemes további erőforrás-pufferrel rendelkeznie, hogy az alkalmazás soha ne érje el a teljesítményszintű korlátot. Ha növeli a számítási méretet, elkerülheti az ügyfél által látható hibákat, amelyek akkor fordulhatnak elő, ha egy adatbázis nem rendelkezik elegendő erőforrással a kérelmek hatékony feldolgozásához, különösen a késésre érzékeny környezetekben.

Más alkalmazástípusok esetén előfordulhat, hogy ugyanazt a gráfot másképp értelmezi. Ha például egy alkalmazás naponta próbál bérszámfejtési adatokat feldolgozni, és ugyanazzal a diagrammal rendelkezik, az ilyen típusú "kötegelt feladat" modell P1 számítási méretben is jól működik. A P1 számítási méret 100 DTU-val rendelkezik, szemben a 200 DTU-val a P2 számítási méretnél. A P1 számítási méret a P2 számítási méret teljesítményének felét biztosítja. A P2 processzorhasználatának 50 százaléka tehát 100 százalékos processzorhasználatot biztosít a P1-ben. Ha az alkalmazás nem rendelkezik időtúllépéssel, akkor nem számít, hogy egy feladat befejezése 2 órát vagy 2,5 órát vesz igénybe, ha ma végzi el. Az ebben a kategóriában lévő alkalmazások valószínűleg használhatnak P1 számítási méretet. Kihasználhatja azt a tényt, hogy a nap folyamán vannak olyan időszakok, amikor az erőforrás-használat alacsonyabb, így bármely kiugró "csúcs" átterjedhet a kisebb terhelésű időszakokra a nap későbbi szakaszában. A P1 számítási mérete jó lehet az ilyen alkalmazásokhoz (és pénzt takaríthat meg), amíg a feladatok minden nap időben befejeződnek.

Az adatbázismotor az egyes logikai kiszolgálók sys.resource_stats adatbázisának master nézetében teszi elérhetővé az egyes aktív adatbázisok felhasznált erőforrás-adatait. A nézetben lévő adatok 5 perces időközökkel lesznek összesítve. Több percig is eltarthat, amíg ezek az adatok megjelennek a táblázatban, így sys.resource_stats hasznosabb az előzményelemzéshez, mint a közel valós idejű elemzéshez. A sys.resource_stats nézet lekérdezésével megtekintheti egy adatbázis legutóbbi előzményeit, és ellenőrizheti, hogy a választott számítási méret adott-e meg a kívánt teljesítményt, amikor szükséges.

Megjegyzés

Az alábbi példákban master lekérdezéséhez csatlakoznia kell a sys.resource_stats adatbázishoz.

Ez a példa a sys.resource_statsadatait mutatja be:

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

A következő példa különböző módokon mutatja be, hogyan használhatja a sys.resource_stats katalógusnézetet, hogy információkat kapjon arról, hogyan használja az adatbázis az erőforrásokat:

  1. A felhasználói adatbázis userdb1múlt heti erőforrás-használatának megtekintéséhez futtassa ezt a lekérdezést a saját adatbázis nevének helyettesítésével:

    SELECT *
    FROM sys.resource_stats
    WHERE database_name = 'userdb1'
          AND start_time > DATEADD(day, -7, GETDATE())
    ORDER BY start_time DESC;
    
  2. Annak kiértékeléséhez, hogy a számítási feladatok mennyire illenek a számítási mérethez, le kell részleteznie az erőforrásmetrikák minden aspektusát: cpu, adat I/O, naplóírás, feldolgozók száma és munkamenetek száma. Íme egy módosított lekérdezés, amely sys.resource_stats használatával jelenti az erőforrásmetrikák átlagos és maximális értékeit az adatbázis által kiosztott összes számítási mérethez:

    SELECT rs.database_name,
           rs.sku,
           MAX(rs.storage_in_megabytes) AS storage_mb,
           AVG(rs.avg_cpu_percent) AS 'Average CPU Utilization In %',
           MAX(rs.avg_cpu_percent) AS 'Maximum CPU Utilization In %',
           AVG(rs.avg_data_io_percent) AS 'Average Data IO In %',
           MAX(rs.avg_data_io_percent) AS 'Maximum Data IO In %',
           AVG(rs.avg_log_write_percent) AS 'Average Log Write Utilization In %',
           MAX(rs.avg_log_write_percent) AS 'Maximum Log Write Utilization In %',
           MAX(rs.max_worker_percent) AS 'Maximum Requests In %',
           MAX(rs.max_session_percent) AS 'Maximum Sessions In %'
    FROM sys.resource_stats AS rs
    WHERE rs.database_name = 'userdb1'
          AND rs.start_time > DATEADD(day, -7, GETDATE())
    GROUP BY rs.database_name, rs.sku;
    
  3. Az egyes erőforrásmetrikák átlagával és maximális értékeivel kapcsolatos információk segítségével felmérheti, hogy a számítási feladatok mennyire illeszkednek a választott számítási mérethez. A sys.resource_stats átlagértékei általában jó alapkonfigurációt biztosítanak a célmérethez képest.

    • DTU vásárlási modell esetén adatbázisokhoz:

      Előfordulhat például, hogy a Standard szolgáltatási szintet használja S2 számítási mérettel. A processzor- és I/O-olvasások és -írások átlagos használati aránya 40 százalék alatt van, a feldolgozók átlagos száma 50 alatt van, a munkamenetek átlagos száma pedig 200 alatt van. Előfordulhat, hogy a számítási feladat belefér az S1 számítási méretébe. Könnyen áttekinthető, hogy az adatbázis megfelel-e a feldolgozó és a munkamenet korlátainak. Annak megállapításához, hogy egy adatbázis kisebb számítási méretre illeszkedik-e, ossza el az alacsonyabb számítási méret DTU-számát az aktuális számítási méret DTU-számával, majd szorozza meg az eredményt 100-zal:

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

      Az eredmény a két számítási méret százalékos relatív teljesítménybeli különbsége. Ha az erőforrás-használat nem haladja meg ezt a százalékot, előfordulhat, hogy a számítási feladat elfér az alacsonyabb számítási méretben. Meg kell azonban vizsgálnia az erőforrás-használati értékek összes tartományát, és százalékban meg kell határoznia, hogy az adatbázis számítási feladatai milyen gyakran férnek el az alacsonyabb számítási mérethez. A következő lekérdezés az erőforrásdimenziónkénti illesztési százalékot adja ki a példában kiszámított 40 százalékos küszöbérték alapján:

      SELECT database_name,
             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 start_time > DATEADD(day, -7, GETDATE())
            AND database_name = 'sample' --remove to see all databases
      GROUP BY database_name;
      

      Az adatbázis-szolgáltatási szint alapján eldöntheti, hogy a számítási feladat megfelel-e az alacsonyabb számítási méretnek. Ha az adatbázis számítási feladatainak célkitűzése 99,9 százalék, és az előző lekérdezés mind a három erőforrásdimenzió esetében 99,9 százaléknál nagyobb értékeket ad vissza, akkor a számítási feladat valószínűleg az alacsonyabb számítási mérethez illeszkedik.

      Az illesztési arány alapján azt is megtudhatja, hogy a cél eléréséhez a következő nagyobb számítási méretre kell-e váltania. Például egy mintaadatbázis processzorhasználata az elmúlt héten:

      Átlagos processzorhasználati százalék Maximális processzorhasználati százalék
      24.5 100,00

      Az átlagos PROCESSZOR a számítási méret korlátjának körülbelül negyede, ami jól illeszkedik az adatbázis számítási méretéhez.

    • DTU vásárlási modell és vCore vásárlási modell adatbázisok esetében:

      A maximális érték azt mutatja, hogy az adatbázis eléri a számítási méret korlátját. Át kell lépnie a következő nagyobb számítási méretre? Nézze meg, hogy a számítási feladat hányszor éri el a 100%-ot, majd hasonlítsa össze az adatbázis számítási feladataival.

      SELECT database_name,
             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 start_time > DATEADD(day, -7, GETDATE())
            AND database_name = 'sample' --remove to see all databases
      GROUP BY database_name;
      

      Ezek a százalékos értékek azt mutatják, hogy a terhelés mintáinak száma hogyan illeszkedik a méret alá a jelenlegi számítási méret alatt. Ha ez a lekérdezés 99,9 százaléknál kisebb értéket ad vissza a három erőforrásdimenzió bármelyikére vonatkozóan, a mintavételezett átlagos számítási feladat túllépte a korlátokat. Fontolja meg, hogy a következő nagyobb számítási méretre lép, vagy alkalmazáshangolási technikákkal csökkenti az adatbázis terhelését.

sys.dm_elastic_pool_resource_stats

Csak az Azure SQL Database vonatkozik

A sys.dm_db_resource_stats-hez hasonlóan a sys.dm_elastic_pool_resource_stats egy rugalmas Azure SQL Database-készlet legutóbbi és részletes erőforrás-használati adatait is biztosítja. A nézet lekérdezhető egy rugalmas készlet bármely adatbázisában, hogy egy adott adatbázis helyett egy teljes készlet erőforrás-használati adatait adja meg. A DMV által jelentett százalékos értékek a rugalmas készlet korlátai felé haladnak, ami magasabb lehet a készletben lévő adatbázis korlátainál.

Ez a példa az aktuális rugalmas készlet összesített erőforrás-használati adatait mutatja be az elmúlt 15 percben:

SELECT dso.elastic_pool_name,
       AVG(eprs.avg_cpu_percent) AS avg_cpu_percent,
       MAX(eprs.avg_cpu_percent) AS max_cpu_percent,
       AVG(eprs.avg_data_io_percent) AS avg_data_io_percent,
       MAX(eprs.avg_data_io_percent) AS max_data_io_percent,
       AVG(eprs.avg_log_write_percent) AS avg_log_write_percent,
       MAX(eprs.avg_log_write_percent) AS max_log_write_percent,
       MAX(eprs.max_worker_percent) AS max_worker_percent,
       MAX(eprs.used_storage_percent) AS max_used_storage_percent,
       MAX(eprs.allocated_storage_percent) AS max_allocated_storage_percent
FROM sys.dm_elastic_pool_resource_stats AS eprs
    CROSS JOIN sys.database_service_objectives AS dso
WHERE eprs.end_time >= DATEADD(minute, -15, GETUTCDATE())
GROUP BY dso.elastic_pool_name;

Ha azt tapasztalja, hogy az erőforrás-használat jelentős ideig megközelíti a 100%, előfordulhat, hogy át kell tekintenie az ugyanazon rugalmas készletben lévő egyes adatbázisok erőforrás-használatát annak megállapításához, hogy az egyes adatbázisok mekkora mértékben járulnak hozzá a készletszintű erőforrás-használathoz.

sys.rugalmas_készlet_erőforrás_statisztikák

Csak az Azure SQL Database vonatkozik

A sys.resource_stats-hez hasonlóan az -adatbázisban található master a logikai kiszolgálón lévő összes rugalmas készlethez biztosít előzményerőforrás-használati adatokat. A sys.elastic_pool_resource_stats az elmúlt 14 napban történő előzményfigyeléshez használhatja, beleértve a használati trend elemzését is.

Ez a példa az aktuális logikai kiszolgálón lévő összes rugalmas készletre vonatkozóan az elmúlt hét nap összesített erőforrás-használati adatait mutatja be. Hajtsa végre a lekérdezést a master adatbázisban.

SELECT elastic_pool_name,
       AVG(avg_cpu_percent) AS avg_cpu_percent,
       MAX(avg_cpu_percent) AS max_cpu_percent,
       AVG(avg_data_io_percent) AS avg_data_io_percent,
       MAX(avg_data_io_percent) AS max_data_io_percent,
       AVG(avg_log_write_percent) AS avg_log_write_percent,
       MAX(avg_log_write_percent) AS max_log_write_percent,
       MAX(max_worker_percent) AS max_worker_percent,
       AVG(avg_storage_percent) AS avg_used_storage_percent,
       MAX(avg_storage_percent) AS max_used_storage_percent,
       AVG(avg_allocated_storage_percent) AS avg_allocated_storage_percent,
       MAX(avg_allocated_storage_percent) AS max_allocated_storage_percent
FROM sys.elastic_pool_resource_stats
WHERE start_time >= DATEADD(day, -7, GETUTCDATE())
GROUP BY elastic_pool_name
ORDER BY elastic_pool_name ASC;

Egyidejű kérések

Az egyidejű kérések aktuális számának megtekintéséhez futtassa ezt a lekérdezést a felhasználói adatbázisban:

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

Ez csak pillanatkép egy adott időpontban. A számítási feladatok és az egyidejű kérések követelményeinek jobb megismeréséhez idővel számos mintát kell összegyűjtenie.

Átlagos kérelemarány

Ez a példa bemutatja, hogyan keresheti meg egy adatbázis vagy egy rugalmas készlet adatbázisainak átlagos kérési arányát egy adott időszakban. Ebben a példában az időtartam 30 másodpercre van állítva. A WAITFOR DELAY utasítás módosításával módosítható. Hajtsa végre ezt a lekérdezést a felhasználói adatbázisban. Ha az adatbázis rugalmas készletben található, és megfelelő engedélyekkel rendelkezik, az eredmények a rugalmas készlet többi adatbázisát is tartalmazzák.

DECLARE @DbRequestSnapshot TABLE (
        database_name sysname PRIMARY KEY,
        total_request_count bigint NOT NULL,
        snapshot_time datetime2 NOT NULL DEFAULT (SYSDATETIME())
);

INSERT INTO @DbRequestSnapshot
(
database_name,
total_request_count
)
SELECT rg.database_name,
       wg.total_request_count
FROM sys.dm_resource_governor_workload_groups AS wg
INNER JOIN sys.dm_user_db_resource_governance AS rg
ON wg.name = CONCAT('UserPrimaryGroup.DBId', rg.database_id);

WAITFOR DELAY '00:00:30';

SELECT rg.database_name,
       (wg.total_request_count - drs.total_request_count) / DATEDIFF(second, drs.snapshot_time, SYSDATETIME()) AS requests_per_second
FROM sys.dm_resource_governor_workload_groups AS wg
INNER JOIN sys.dm_user_db_resource_governance AS rg
ON wg.name = CONCAT('UserPrimaryGroup.DBId', rg.database_id)
INNER JOIN @DbRequestSnapshot AS drs
ON rg.database_name = drs.database_name;

Aktuális munkamenetek

Az aktuális aktív munkamenetek számának megtekintéséhez futtassa ezt a lekérdezést az adatbázisban:

SELECT COUNT(*) AS [Sessions]
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;

Ez a lekérdezés egy időponthoz kötött számot ad vissza. Ha többször gyűjt mintákat az idő múlásával, akkor a legjobban megérti a munkamenetek használatát.

A kérések, munkamenetek és munkavállalók legutóbbi előzményei

Ez a példa egy adatbázis vagy egy rugalmas készlet adatbázisainak kéréseinek, munkameneteinek és feldolgozószálainak legutóbbi előzményhasználatát adja vissza. Minden sor az erőforrás-használat pillanatképét jeleníti meg egy adott időpontban egy adatbázishoz. A requests_per_second oszlop az snapshot_timevégződő időintervallum átlagos kérési sebessége. Ha az adatbázis rugalmas készletben található, és megfelelő engedélyekkel rendelkezik, az eredmények a rugalmas készlet többi adatbázisát is tartalmazzák.

SELECT rg.database_name,
       wg.snapshot_time,
       wg.active_request_count,
       wg.active_worker_count,
       wg.active_session_count,
       CAST (wg.delta_request_count AS DECIMAL) / duration_ms * 1000 AS requests_per_second
FROM sys.dm_resource_governor_workload_groups_history_ex AS wg
     INNER JOIN sys.dm_user_db_resource_governance AS rg
         ON wg.name = CONCAT('UserPrimaryGroup.DBId', rg.database_id)
ORDER BY snapshot_time DESC;

Adatbázis- és objektumméretek kiszámítása

Az alábbi lekérdezés az adatbázis adatméretét adja vissza (megabájtban):

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

Az alábbi lekérdezés visszaadja az adatbázisban található egyes objektumok méretét (megabájtban):

-- Calculates the size of individual database objects.
SELECT o.name,
       SUM(ps.reserved_page_count) * 8.0 / 1024 AS size_mb
FROM sys.dm_db_partition_stats AS ps
     INNER JOIN sys.objects AS o
         ON ps.object_id = o.object_id
GROUP BY o.name
ORDER BY size_mb DESC;

Cpu-teljesítményproblémák azonosítása

Ez a szakasz segít azonosítani azokat az egyedi lekérdezéseket, amelyeknek a legnagyobb processzorfelhasználásuk van.

Ha a processzorhasználat hosszabb ideig 80% felett van, vegye figyelembe az alábbi hibaelhárítási lépéseket, hogy a cpu-probléma most vagy fordult elő az elmúlt. Az ebben a szakaszban leírt lépéseket követve proaktív módon azonosíthatja és hangolhatja a legfontosabb processzorhasználati lekérdezéseket. Bizonyos esetekben a processzorhasználat csökkentése lehetővé teszi az adatbázisok és a rugalmas készletek vertikális leskálázását, és csökkentheti a költségeket.

A hibaelhárítási lépések ugyanazok, mint a rugalmas készletben lévő önálló adatbázisok és adatbázisok esetében. Hajtsa végre az összes lekérdezést a felhasználói adatbázisban.

A cpu-probléma most jelentkezik

Ha a probléma jelenleg is fennáll, két lehetséges forgatókönyv lehetséges:

Sok egyedi lekérdezés, amelyek halmozottan magas processzorhasználatot használnak fel

A következő lekérdezéssel azonosíthatja a leggyakoribb lekérdezéseket lekérdezéskivonat alapján:

PRINT '-- top 10 Active CPU Consuming Queries (aggregated)--';
SELECT TOP 10 GETDATE() AS runtime,
              *
FROM (SELECT query_stats.query_hash,
             SUM(query_stats.cpu_time) AS 'Total_Request_Cpu_Time_Ms',
             SUM(logical_reads) AS 'Total_Request_Logical_Reads',
             MIN(start_time) AS 'Earliest_Request_start_Time',
             COUNT(*) AS '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;

A processzort használó, hosszú ideig futó lekérdezések továbbra is futnak

A következő lekérdezésekkel azonosíthatja ezeket a lekérdezéseket:

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

A processzorral kapcsolatos probléma a múltban fordult elő

Ha a probléma a múltban történt, és alapvető okelemzést szeretne végezni, használja Lekérdezéstár. Az adatbázis-hozzáféréssel rendelkező felhasználók a T-SQL használatával kérdezhetik le a lekérdezéstár adatait. A Lekérdezéstár alapértelmezés szerint egyórás időközök összesített lekérdezési statisztikáit rögzíti.

  1. Az alábbi lekérdezéssel megtekintheti a magas processzorhasználatú lekérdezések tevékenységeit. Ez a lekérdezés a 15 processzort használó lekérdezést adja vissza. Ne felejtse el módosítani rsi.start_time >= DATEADD(hour, -2, GETUTCDATE(), hogy az elmúlt két órától eltérő időszakot tekintsen meg:

    -- Top 15 CPU consuming queries by query hash
    -- Note that a query hash can have many query ids if not parameterized or not parameterized properly
    WITH AggregatedCPU
    AS (SELECT q.query_hash,
               SUM(count_executions * avg_cpu_time / 1000.0) AS total_cpu_ms,
               SUM(count_executions * avg_cpu_time / 1000.0) / SUM(count_executions) AS avg_cpu_ms,
               MAX(rs.max_cpu_time / 1000.00) AS max_cpu_ms,
               MAX(max_logical_io_reads) AS 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
             INNER JOIN sys.query_store_query AS q
                 ON qt.query_text_id = q.query_text_id
             INNER JOIN sys.query_store_plan AS p
                 ON q.query_id = p.query_id
             INNER JOIN sys.query_store_runtime_stats AS rs
                 ON rs.plan_id = p.plan_id
             INNER 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_ms,
               avg_cpu_ms,
               max_cpu_ms,
               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_ms DESC, query_hash ASC) AS query_hash_row_number
        FROM AggregatedCPU)
    SELECT OD.query_hash,
           OD.total_cpu_ms,
           OD.avg_cpu_ms,
           OD.max_cpu_ms,
           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.query_hash_row_number
    FROM OrderedCPU AS OD
    WHERE OD.query_hash_row_number <= 15 --get top 15 rows by total_cpu_ms
    ORDER BY total_cpu_ms DESC;
    
  2. Miután azonosította a problémás lekérdezéseket, ideje hangolni ezeket a lekérdezéseket a processzorhasználat csökkentése érdekében. Másik lehetőségként az adatbázis vagy a rugalmas készlet számítási méretének növelését is választhatja a probléma megoldásához.

Az Azure SQL Database processzorteljesítményével kapcsolatos problémák kezelésével kapcsolatos további információkért lásd: Magas processzorhasználat diagnosztizálása és hibaelhárítása az Azure SQL Database-ben és az SQL Database-ben a Microsoft Fabricben.

Az I/O teljesítményproblémáinak azonosítása

A tárolási bemeneti/kimeneti (I/O) teljesítményproblémák azonosításakor a legfontosabb várakozási típusok a következők:

  • PAGEIOLATCH_*

    Adatfájl I/O-problémái esetén (beleértve PAGEIOLATCH_SH, PAGEIOLATCH_EX, PAGEIOLATCH_UP). Ha a várakozási típus neve IO- szerepel benne, az I/O-problémára mutat. Ha a lapzárolási várakozás neve nem tartalmaz IO-t, ez egy másik típusú problémára mutat, amely nem kapcsolódik a tárolási teljesítményhez (például tempdb versengéshez).

  • WRITE_LOG

    Tranzakciónapló I/O-problémái esetén.

Ha az I/O-probléma jelenleg jelentkezik

A sys.dm_exec_requests vagy a sys.dm_os_waiting_tasks használatával megtekintheti a wait_type és a wait_time.

Az adatok és naplók I/O-használatának azonosítása

Az alábbi lekérdezés használatával azonosíthatja az adatokat, és naplózhatja az I/O-használatot.

SELECT DB_NAME() AS database_name,
       end_time AS UTC_time,
       rs.avg_data_io_percent AS 'Data IO In % of Limit',
       rs.avg_log_write_percent AS 'Log Write Utilization In % of Limit'
FROM sys.dm_db_resource_stats AS rs --past hour only
ORDER BY rs.end_time DESC;

A sys.dm_db_resource_statshasználatával kapcsolatos további példákért tekintse meg a cikk későbbi, Erőforrás-használat figyelése szakaszát.

Ha elérte az I/O-korlátot, két lehetősége van:

  • A számítási méret vagy a szolgáltatási szint frissítése
  • Azonosítsa és hangolja a legtöbb I/O-t használó lekérdezéseket.

A leggyakoribb lekérdezések I/O-val kapcsolatos várakozások alapján történő azonosításához a következő Lekérdezéstár lekérdezéssel tekintheti meg a nyomon követett tevékenység utolsó két óráját:

-- 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
                         INNER JOIN sys.query_store_query AS q ON qt.query_text_id=q.query_text_id
                         INNER JOIN sys.query_store_plan AS p ON q.query_id=p.query_id
                         INNER JOIN sys.query_store_wait_stats AS waits ON waits.plan_id=p.plan_id
                         INNER 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 query_hash_row_number
                                                        FROM Aggregated)
SELECT OD.query_hash, OD.total_executions, OD.total_wait_time_ms, OD.sampled_query_text, OD.wait_category_desc, OD.query_hash_row_number
FROM Ordered AS OD
WHERE OD.query_hash_row_number <= 15 -- get top 15 rows by total_wait_time_ms
ORDER BY total_wait_time_ms DESC;
GO

Használhatja a sys.query_store_runtime_stats nézetet is, amely a avg_physical_io_reads és avg_num_physical_io_reads oszlopban lévő nagy értékeket tartalmazó lekérdezésekre összpontosít.

A teljes napló I/O megtekintése a WRITELOG várakozásokhoz

Ha a várakozási típus WRITELOG: a következő lekérdezéssel megtekintheti a teljes napló I/O-t lekérdezésenként.

-- 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_ms,
           SUM(count_executions * avg_cpu_time / 1000.0) / SUM(count_executions) AS avg_cpu_ms,
           SUM(count_executions * avg_log_bytes_used) AS total_log_bytes_used,
           MAX(rs.max_cpu_time / 1000.00) AS max_cpu_ms,
           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
        INNER JOIN sys.query_store_query AS q ON qt.query_text_id = q.query_text_id
        INNER JOIN sys.query_store_plan AS p ON q.query_id = p.query_id
        INNER JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = p.plan_id
        INNER 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 query_hash_row_number
    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.query_hash_row_number
FROM OrderedLogUsed AS OD
WHERE OD.query_hash_row_number <= 15 -- get top 15 rows by total_log_bytes_used
ORDER BY total_log_bytes_used DESC;
GO

Tempdb-teljesítményproblémák azonosítása

A tempdb problémákhoz társított gyakori várakozási típus a PAGELATCH_* (nem PAGEIOLATCH_*). A várakozások azonban nem mindig jelentik azt, PAGELATCH_* hogy versengés van tempdb . Ez a várakozás azt is jelentheti, hogy a felhasználó-objektum adatoldali versengés az ugyanazon adatoldalt megcélzó egyidejű kérések miatt is előfordulhat. A tempdb versengés további megerősítéséhez használja a sys.dm_exec_requests annak ellenőrzésére, hogy a wait_resource érték azzal kezdődik, hogy 2:x:y, ahol a 2 tempdb az adatbázis azonosítója, x a fájlazonosító, és y az oldalazonosító.

Gyakori módszer a tempdb versengés esetén a tempdb-ra támaszkodó alkalmazáskód csökkentése vagy átírása. Gyakori tempdb használati területek:

  • Ideiglenes táblák
  • Táblaváltozók
  • Táblaértékkel megadott paraméterek
  • Olyan lekérdezések, amelyek lekérdezési tervekkel rendelkeznek, amelyek rendezéseket, kivonat-illesztéseket és sorokat használnak

További információkért tekintse meg a tempdb az Azure SQL.

A rugalmas készlet összes adatbázisa közösen használja az tempdb adatbázist. Az egyik adatbázis magas tempdb területkihasználtsága hatással lehet az ugyanabban a rugalmas készletben lévő többi adatbázisra.

Táblaváltozókat és ideiglenes táblákat használó leggyakoribb lekérdezések

A következő lekérdezés használatával azonosíthatja a táblaváltozókat és ideiglenes táblákat használó leggyakoribb lekérdezéseket:

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)') AS 'Database'
, stmt.stmt_details.value('@Schema', 'varchar(max)') AS 'Schema'
, stmt.stmt_details.value('@Table', 'varchar(max)') AS '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
        INNER JOIN #tmpPlan AS t2 ON t.plan_handle=t2.plan_handle;
GO
DROP TABLE #tmpPlan
DROP TABLE #tmp2

Hosszú ideig futó tranzakciók azonosítása

A hosszú ideig futó tranzakciók azonosításához használja az alábbi lekérdezést. A hosszú ideig futó tranzakciók megakadályozzák az állandó verziótár (PVS) törlését. További információk: Felgyorsított adatbázis-helyreállítás hibaelhárítása.

SELECT DB_NAME(dtr.database_id) AS 'database_name',
       sess.session_id,
       atr.name AS 'tran_name',
       atr.transaction_id,
       transaction_type,
       transaction_begin_time,
       database_transaction_begin_time,
       transaction_state,
       is_user_transaction,
       sess.open_transaction_count,
       TRIM(REPLACE(
                REPLACE(
                            SUBSTRING(
                                        SUBSTRING(
                                                    txt.text,
                                                    (req.statement_start_offset / 2) + 1,
                                                    ((CASE req.statement_end_offset
                                                            WHEN -1 THEN
                                                                DATALENGTH(txt.text)
                                                            ELSE
                                                                req.statement_end_offset
                                                        END - req.statement_start_offset
                                                    ) / 2
                                                    ) + 1
                                                ),
                                        1,
                                        1000
                                    ),
                            CHAR(10),
                            ' '
                        ),
                CHAR(13),
                ' '
            )
            ) Running_stmt_text,
       recenttxt.text 'MostRecentSQLText'
FROM sys.dm_tran_active_transactions AS atr
     INNER JOIN sys.dm_tran_database_transactions AS dtr
         ON dtr.transaction_id = atr.transaction_id
     LEFT OUTER JOIN sys.dm_tran_session_transactions AS sess
         ON sess.transaction_id = atr.transaction_id
     LEFT OUTER JOIN sys.dm_exec_requests AS req
         ON req.session_id = sess.session_id
        AND req.transaction_id = sess.transaction_id
     LEFT OUTER 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;

Memória-hozzáférési várakozási teljesítménnyel kapcsolatos problémák azonosítása

Ha a legnagyobb várakozási típus RESOURCE_SEMAPHORE, előfordulhat, hogy memória-hozzárendelési várakozási problémát tapasztal, ami miatt a lekérdezések csak akkor kezdhetik meg a végrehajtást, ha elég nagy memória-hozzárendelést kapnak.

Annak meghatározása, hogy a RESOURCE_SEMAPHORE várakozás a legmagasabb várakozási idő-e

Az alábbi lekérdezéssel megállapíthatja, hogy a RESOURCE_SEMAPHORE várakozás a legnagyobb várakozási idő-e. Az RESOURCE_SEMAPHORE várakozási idő rang növekedése is jelezheti a közelmúltat. A memóriakiadások várakozási problémáinak elhárításával kapcsolatos további információkért lásd: Az SQL Servermemóriakiadásai által okozott lassú vagy kevés memóriaproblémák elhárítása.

SELECT wait_type,
       SUM(wait_time) AS total_wait_time_ms
FROM sys.dm_exec_requests AS req
     INNER 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;

Nagy memóriaigényű utasítások azonosítása

Ha memóriahiba lépett fel az Azure SQL Database-ben, tekintse át sys.dm_os_out_of_memory_events. További információ: Az Azure SQL Database és a Fabric SQL Database memóriakihasználtságával kapcsolatos hibák elhárítása.

Először módosítsa a következő szkriptet a start_time és end_timevonatkozó értékeinek frissítéséhez. Ezután futtassa a következő lekérdezést a nagy memóriaigényű utasítások azonosításához:

SELECT IDENTITY (INT, 1, 1) AS rowId,
       CAST (query_plan AS XML) AS query_plan,
       p.query_id
INTO #tmp
FROM sys.query_store_plan AS p
     INNER JOIN sys.query_store_runtime_stats AS r
         ON p.plan_id = r.plan_id
     INNER 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';

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)) AS SerialDesiredMemory_MB
FROM cte
     INNER JOIN sys.query_store_query AS q
         ON cte.query_id = q.query_id
     INNER JOIN sys.query_store_query_text AS t
         ON q.query_text_id = t.query_text_id
ORDER BY SerialDesiredMemory DESC;

A 10 legfontosabb aktív memóriatámogatás azonosítása

Az alábbi lekérdezés segítségével azonosíthatja a 10 legfontosabb aktív memória-támogatást:

SELECT TOP 10 CONVERT(VARCHAR(30), GETDATE(), 121) AS runtime,
              r.session_id,
              r.blocking_session_id,
              r.cpu_time,
              r.total_elapsed_time,
              r.reads,
              r.writes,
              r.logical_reads,
              r.row_count,
              wait_time,
              wait_type,
              r.command,
              OBJECT_NAME(txt.objectid, txt.dbid) 'Object_Name',
              TRIM(REPLACE(REPLACE(SUBSTRING(SUBSTRING(TEXT, (r.statement_start_offset / 2) + 1, 
               (  (
                   CASE r.statement_end_offset
                       WHEN - 1
                           THEN DATALENGTH(TEXT)
                       ELSE r.statement_end_offset
                       END - r.statement_start_offset
                   ) / 2
               ) + 1), 1, 1000), CHAR(10), ' '), CHAR(13), ' ')) AS 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
     INNER 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;

Kapcsolatok figyelése

A sys.dm_exec_connections nézetben lekérheti az adott adatbázishoz létesített kapcsolatokra és az egyes kapcsolatok részleteire vonatkozó információkat. Ha egy adatbázis rugalmas készletben található, és rendelkezik megfelelő engedélyekkel, a nézet visszaadja a rugalmas készletben lévő összes adatbázis kapcsolatkészletét. Emellett a sys.dm_exec_sessions nézet hasznos az összes aktív felhasználói kapcsolatra és belső feladatra vonatkozó információk lekérésekor.

Aktuális munkamenetek megtekintése

Az alábbi lekérdezés az aktuális kapcsolat és munkamenet adatait kéri le. Az összes kapcsolat és munkamenet megtekintéséhez távolítsa el a WHERE záradékot.

Az összes végrehajtó munkamenet csak akkor jelenik meg az adatbázisban, ha VIEW DATABASE STATE engedéllyel rendelkezik az adatbázisra a sys.dm_exec_requests és sys.dm_exec_sessions nézetek végrehajtásakor. Ellenkező esetben csak az aktuális munkamenet jelenik meg.

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
     INNER JOIN sys.dm_exec_sessions AS s
         ON c.session_id = s.session_id
WHERE c.session_id = @@SPID; --Remove to view all sessions, if permissions allow

Lekérdezési teljesítmény figyelése

A lassú vagy hosszú ideig futó lekérdezések jelentős rendszererőforrásokat használhatnak fel. Ez a szakasz bemutatja, hogyan lehet dinamikus felügyeleti nézetekkel észlelni néhány gyakori lekérdezési teljesítményproblémát a sys.dm_exec_query_stats dinamikus felügyeleti nézet használatával. A nézet minden lekérdezési utasításhoz egy sort tartalmaz a gyorsítótárban tárolt tervben, és a sorok élettartama magához a tervhez kötődik. Ha egy tervet eltávolít a gyorsítótárból, a megfelelő sorok törlődnek ebből a nézetből. Ha egy lekérdezés nem rendelkezik gyorsítótárazott tervvel, például mert OPTION (RECOMPILE) van használatban, akkor nem fog megjelenni az eredmények között ebben a nézetben.

Leggyakoribb lekérdezések keresése processzoridő szerint

Az alábbi példa az első 15 lekérdezés adatait adja vissza a végrehajtásonkénti átlagos cpu-idő alapján rangsorolva. Ez a példa a lekérdezéseket a lekérdezés kivonata alapján összesíti, így a logikailag egyenértékű lekérdezések az összesített erőforrás-felhasználásuk szerint vannak csoportosítva.

SELECT TOP 15 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 Avg_CPU_Time DESC;

Lekérdezéstervek figyelése az összesített CPU-idő szempontjából

A nem hatékony lekérdezési terv a processzorhasználatot is növelheti. Az alábbi példa azt határozza meg, hogy melyik lekérdezés használja a legutóbbi előzmények legnagyobb összegző processzorát.

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 15 qs.plan_handle,
                    qs.total_worker_time
      FROM sys.dm_exec_query_stats AS 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;

Letiltott lekérdezések figyelése

A lassú vagy hosszú ideig futó lekérdezések hozzájárulhatnak a túlzott erőforrás-felhasználáshoz, és a blokkolt lekérdezések következményei lehetnek. A blokkolás oka lehet az alkalmazás rossz kialakítása, a rossz lekérdezési tervek, a hasznos indexek hiánya stb.

A sys.dm_tran_locks nézetben információkat kaphat az adatbázis aktuális zárolási tevékenységéről. Példák a kódra, lásd: sys.dm_tran_locks. A blokkolás hibaelhárításáról további információt a blokkolási problémák ismertetése és megoldása című témakörben talál.

Holtpontok monitorozása

Bizonyos esetekben két vagy több lekérdezés blokkolhatja egymást, ami holtpontot eredményez.

Létrehozhat egy kiterjesztett események nyomkövetését a holtponti események rögzítéséhez, majd megkeresheti a kapcsolódó lekérdezéseket és azok végrehajtási terveit a Lekérdezéstárban. További információ: Holtpontok elemzése és megakadályozása az Azure SQL Database-ben és az SQL Database-ben a Fabricben. További információ a holtpontokról a Holtpontok útmutatóban.

Engedélyek

Az Azure SQL Database-ben a számítási mérettől, az üzembe helyezési lehetőségtől és a DMV adataitól függően a DMV lekérdezéséhez VIEW DATABASE STATEvagy VIEW SERVER PERFORMANCE STATEvagy VIEW SERVER SECURITY STATE engedélyre lehet szükség. Az utolsó két engedély szerepel a VIEW SERVER STATE engedélyben. A kiszolgáló állapotmegtekintési engedélyeket a megfelelő kiszolgálói szerepkörökbenlévő tagsággal adják meg. Egy adott DMV lekérdezéséhez szükséges engedélyek meghatározásához tekintse meg a rendszer dinamikus felügyeleti nézeteit , és keresse meg a DMV-t leíró cikket.

A VIEW DATABASE STATE jogosultságának megadásához egy adatbázis-felhasználónak futtassa a következő lekérdezést, és cserélje le a database_user-t az adatbázisban lévő felhasználói fiók nevére:

GRANT VIEW DATABASE STATE TO [database_user];

Ha egy ##MS_ServerStateReader##login_name nevű bejelentkezéshez szeretne tagságot adni a kiszolgálói szerepkörben, csatlakozzon a master adatbázishoz, majd futtassa példaként a következő lekérdezést:

ALTER SERVER ROLE [##MS_ServerStateReader##] ADD MEMBER [login_name];

Az engedély megadásának érvénybe lépése eltarthat néhány percig. További információ: Kiszolgálószintű szerepkörök korlátozásai.