Memantau performa Microsoft Azure SQL Managed Instance menggunakan tampilan manajemen dinamis
Berlaku untuk: Azure SQL Managed Instance
Microsoft Azure SQL Managed Instance memungkinkan subset tampilan manajemen dinamis (DMV) untuk mendiagnosis masalah performa, yang mungkin disebabkan oleh kueri yang diblokir atau berjalan lama, penyempitan sumber daya, rencana kueri yang buruk, dan sebagainya. Artikel ini memberi informasi tentang cara mendeteksi masalah performa umum dengan menggunakan tampilan manajemen dinamis.
Artikel ini berisi tentang Azure SQL Managed Instance, lihat juga Memantau performa Microsoft Azure SQL Database menggunakan tampilan manajemen dinamis.
Izin
Di Azure SQL Managed Instance, mengkueri tampilan manajemen dinamis memerlukan izin TAMPILKAN STATUS DATABASE.
GRANT VIEW SERVER STATE TO database_user;
Dalam instans SQL Server dan di Azure SQL Managed Instance, tampilan manajemen dinamis mengembalikan informasi status server.
Mengidentifikasi masalah performa CPU
Jika penggunaan CPU di atas 80% untuk jangka waktu yang lama, pertimbangkan langkah-langkah pemecahan masalah berikut:
Masalah CPU sedang terjadi sekarang
Jika masalah terjadi saat ini, ada dua skenario yang mungkin:
Banyak kueri individu yang secara kumulatif penggunaan CPUnya tinggi
Gunakan kueri berikut untuk mengidentifikasi hash kueri teratas:
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;
Kueri yang berjalan lama yang menggunakan CPU masih berjalan
Gunakan kueri berikut untuk mengidentifikasi kueri ini:
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
Jika masalah CPU terjadi di masa lalu
Jika masalah terjadi di masa lalu dan Anda ingin melakukan analisis akar penyebab, gunakan Penyimpanan Kueri. Pengguna dengan akses database bisa menggunakan T-SQL untuk mengkueri data Query Store. Konfigurasi default Query Store menggunakan granularitas 1 jam. Gunakan kueri berikut untuk melihat aktivitas untuk kueri penggunaan CPUnya tinggi. Kueri ini mengembalikan 15 kueri teratas yang memakan CPU. Ingatlah untuk mengubah 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;
Setelah Anda mengidentifikasi kueri yang bermasalah, saatnya untuk menyetel kueri tersebut untuk mengurangi pemanfaatan CPU. Jika Anda tidak punya waktu untuk menyetel kueri, Anda juga dapat memilih untuk meningkatkan SLO instans terkelola untuk mengatasi masalah tersebut.
Mengidentifikasi masalah performa IO
Saat mengidentifikasi masalah kinerja IO, jenis tunggu terbanyak yang terkait dengan masalah IO adalah:
PAGEIOLATCH_*
Untuk masalah IO file data (termasuk
PAGEIOLATCH_SH
,PAGEIOLATCH_EX
,PAGEIOLATCH_UP
). Jika nama jenis tunggu memiliki IO di dalamnya, itu menunjukkan masalah IO. Jika tidak ada IO di nama tunggu kait halaman, itu menunjuk ke jenis masalah yang berbeda (misalnya,tempdb
ketidakcocokan).WRITE_LOG
Untuk masalah log IO transaksi.
Jika masalah IO terjadi sekarang
Gunakan sys.dm_exec_requests atau sys.dm_os_waiting_tasks untuk melihat wait_type
dan wait_time
.
Menampilkan IO terkait buffer menggunakan Query Store
Untuk opsi 2, Anda bisa menggunakan kueri berikut ini terhadap Query Store untuk IO terkait buffer untuk menampilkan dua jam terakhir aktivitas terlacak:
-- 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
Lihat total log IO untuk WRITELOG tunggu
Jika jenis tunggu adalah WRITELOG
, gunakan kueri berikut ini untuk menampilkan total log IO menurut pernyataan:
-- 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
Mengidentifikasi masalah performa tempdb
Saat mengidentifikasi masalah performa IO, jenis tunggu teratas yang terkait dengan masalah tempdb
adalah PAGELATCH_*
(bukan PAGEIOLATCH_*
). Namun, PAGELATCH_*
menunggu tidak selalu berarti Anda memiliki ketidakcocokan tempdb
. Waktu tunggu ini juga dapat berarti bahwa Anda memiliki ketidakcocokan halaman data objek pengguna karena permintaan bersamaan yang menargetkan halaman data yang sama. Untuk mengkonfirmasi lebih lanjut ketidakcocokan tempdb
, gunakan sys.dm_exec_requests untuk mengonfirmasi bahwa nilai wait_resource dimulai dengan 2:x:y
di mana 2 adalah tempdb
merupakan ID database, x
adalah ID file, dan y
adalah ID halaman.
Untuk tempdb
ketidakcocokan, metode umum adalah mengurangi atau menulis ulang kode aplikasi yang bergantung pada tempdb
. Area penggunaan tempdb
umum meliputi:
- Tabel sementara
- Variabel tabel
- Parameter bernilai tabel
- Penggunaan penyimpanan versi (terkait dengan transaksi yang berjalan lama)
- Kueri yang memiliki rencana kueri yang menggunakan pengurutan, gabungan hash, dan tampungan
Kueri teratas yang menggunakan variabel tabel dan tabel sementara
Anda dapat menggunakan kueri berikut untuk mengidentifikasi kueri teratas yang menggunakan variabel tabel dan tabel sementara:
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;
Mengidentifikasi transaksi yang berjalan lama
Gunakan kueri berikut untuk mengidentifikasi transaksi yang berjalan lama. Transaksi yang berjalan lama mencegah penghapusan penyimpanan versi.
SELECT DB_NAME(dtr.database_id) 'database_name',
sess.session_id,
atr.name AS 'tran_name',
atr.transaction_id,
transaction_type,
transaction_begin_time,
database_transaction_begin_time,
transaction_state,
is_user_transaction,
sess.open_transaction_count,
TRIM(REPLACE(
REPLACE(
SUBSTRING(
SUBSTRING(
txt.text,
(req.statement_start_offset / 2) + 1,
((CASE req.statement_end_offset
WHEN -1 THEN
DATALENGTH(txt.text)
ELSE
req.statement_end_offset
END - req.statement_start_offset
) / 2
) + 1
),
1,
1000
),
CHAR(10),
' '
),
CHAR(13),
' '
)
) Running_stmt_text,
recenttxt.text 'MostRecentSQLText'
FROM sys.dm_tran_active_transactions AS atr
INNER JOIN sys.dm_tran_database_transactions AS dtr
ON dtr.transaction_id = atr.transaction_id
LEFT JOIN sys.dm_tran_session_transactions AS sess
ON sess.transaction_id = atr.transaction_id
LEFT JOIN sys.dm_exec_requests AS req
ON req.session_id = sess.session_id
AND req.transaction_id = sess.transaction_id
LEFT JOIN sys.dm_exec_connections AS conn
ON sess.session_id = conn.session_id
OUTER APPLY sys.dm_exec_sql_text(req.sql_handle) AS txt
OUTER APPLY sys.dm_exec_sql_text(conn.most_recent_sql_handle) AS recenttxt
WHERE atr.transaction_type != 2
AND sess.session_id != @@spid
ORDER BY start_time ASC;
Mengidentifikasi masalah performa tunggu peruntukan memori
Jika jenis tunggu teratas Anda RESOURCE_SEMAHPORE
adalah dan Anda tidak memiliki masalah penggunaan CPU yang tinggi, Anda mungkin memiliki masalah tunggu peruntukan memori.
Menentukan apakah RESOURCE_SEMAHPORE
tunggu adalah tunggu teratas
Menggunakan kueri berikut untuk menentukan apakah RESOURCE_SEMAHPORE
tunggu adalah tunggu teratas
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;
Mengidentifikasi pernyataan yang penggunaan memorinya tinggi
Jika Anda menemukan kesalahan memori habis, tinjau sys.dm_os_out_of_memory_events.
Gunakan kueri berikut untuk mengidentifikasi pernyataan yang penggunaan memorinya tinggi:
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;
Mengidentifikasi hibah memori
Gunakan kueri berikut untuk mengidentifikasi 10 hibah memori aktif teratas:
SELECT TOP 10
CONVERT(VARCHAR(30), GETDATE(), 121) AS runtime,
r.session_id,
r.blocking_session_id,
r.cpu_time,
r.total_elapsed_time,
r.reads,
r.writes,
r.logical_reads,
r.row_count,
wait_time,
wait_type,
r.command,
OBJECT_NAME(txt.objectid, txt.dbid) 'Object_Name',
TRIM(REPLACE(
REPLACE(
SUBSTRING(
SUBSTRING(
text,
(r.statement_start_offset / 2) + 1,
((CASE r.statement_end_offset
WHEN -1 THEN
DATALENGTH(text)
ELSE
r.statement_end_offset
END - r.statement_start_offset
) / 2
) + 1
),
1,
1000
),
CHAR(10),
' '
),
CHAR(13),
' '
)
) stmt_text,
mg.dop, --Degree of parallelism
mg.request_time, --Date and time when this query requested the memory grant.
mg.grant_time, --NULL means memory has not been granted
mg.requested_memory_kb / 1024.0 requested_memory_mb, --Total requested amount of memory in megabytes
mg.granted_memory_kb / 1024.0 AS granted_memory_mb, --Total amount of memory actually granted in megabytes. NULL if not granted
mg.required_memory_kb / 1024.0 AS required_memory_mb, --Minimum memory required to run this query in megabytes.
max_used_memory_kb / 1024.0 AS max_used_memory_mb,
mg.query_cost, --Estimated query cost.
mg.timeout_sec, --Time-out in seconds before this query gives up the memory grant request.
mg.resource_semaphore_id, --Non-unique ID of the resource semaphore on which this query is waiting.
mg.wait_time_ms, --Wait time in milliseconds. NULL if the memory is already granted.
CASE mg.is_next_candidate --Is this process the next candidate for a memory grant
WHEN 1 THEN
'Yes'
WHEN 0 THEN
'No'
ELSE
'Memory has been granted'
END AS 'Next Candidate for Memory Grant',
qp.query_plan
FROM sys.dm_exec_requests AS r
JOIN sys.dm_exec_query_memory_grants AS mg
ON r.session_id = mg.session_id
AND r.request_id = mg.request_id
CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS txt
CROSS APPLY sys.dm_exec_query_plan(r.plan_handle) AS qp
ORDER BY mg.granted_memory_kb DESC;
Menghitung ukuran database dan objek
Kueri berikut mengembalikan ukuran database Anda (dalam megabyte):
-- 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
Kueri berikut mengembalikan ukuran objek individual (dalam megabyte) di database Anda:
-- 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
Memantau koneksi
Anda dapat menggunakan tampilan sys.dm_exec_connections untuk mengambil informasi tentang koneksi yang dibuat ke instans terkelola tertentu dan detail setiap koneksi. Selain itu, tampilan sys.dm_exec_sessions sangat membantu saat mengambil informasi tentang semua koneksi pengguna aktif dan tugas internal.
Kueri berikut ini mengambil informasi tentang koneksi saat ini:
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;
Memantau penggunaan sumber daya
Anda dapat memantau penggunaan sumber daya menggunakan Penyimpanan Kueri, seperti yang Anda lakukan di SQL Server.
Anda juga dapat memantau penggunaan menggunakan sys.dm_db_resource_stats dan sys.server_resource_stats.
sys.dm_db_sumberdaya_stats
Anda bisa menggunakan tampilan sys.dm_db_resource_stats di setiap database. sys.dm_db_resource_stats
Tampilan menunjukkan data penggunaan sumber daya terbaru relatif terhadap tingkat layanan. Persentase rata-rata untuk CPU, IO data, tulis log, dan memori direkam setiap 15 detik dan dipertahankan selama 1 jam.
Karena tampilan ini memberikan tampilan yang lebih terperinci tentang penggunaan sumber daya, gunakan sys.dm_db_resource_stats
terlebih dahulu untuk analisis atau pemecahan masalah saat ini. Misalnya, kueri ini memperlihatkan penggunaan sumber daya rata-rata dan maksimum untuk database saat ini selama satu jam terakhir:
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;
Untuk kueri lain, lihat contoh dalam sys.dm_db_resource_stats.
sys.server_resource_stats
Anda dapat menggunakan sys.server_resource_stats untuk mengembalikan penggunaan CPU, IO, dan data penyimpanan untuk Azure SQL Managed Instance. Data dikumpulkan dan diagregasi dalam interval lima menit. Ada satu baris untuk setiap 15 detik pelaporan. Data yang dikembalikan mencakup penggunaan CPU, ukuran penyimpanan, pemanfaatan IO, dan SKU instans terkelola. Data historis disimpan selama sekitar 14 hari.
Contoh menunjukkan berbagai cara agar Anda dapat menggunakan sys.server_resource_stats
tampilan katalog untuk mendapatkan informasi tentang cara instans Anda menggunakan sumber daya.
Contoh berikut mengembalikan penggunaan CPU rata-rata selama tujuh hari terakhir:
DECLARE @s datetime; DECLARE @e datetime; SET @s= DateAdd(d,-7,GetUTCDate()); SET @e= GETUTCDATE(); SELECT AVG(avg_cpu_percent) AS Average_Compute_Utilization FROM sys.server_resource_stats WHERE start_time BETWEEN @s AND @e; GO
Contoh berikut mengembalikan ruang penyimpanan rata-rata yang digunakan oleh instans Anda per hari, untuk memungkinkan analisis tren pertumbuhan:
DECLARE @s datetime; DECLARE @e datetime; SET @s= DateAdd(d,-7,GetUTCDate()); SET @e= GETUTCDATE(); SELECT Day = convert(date, start_time), AVG(storage_space_used_mb) AS Average_Space_Used_mb FROM sys.server_resource_stats WHERE start_time BETWEEN @s AND @e GROUP BY convert(date, start_time) ORDER BY convert(date, start_time); GO
Permintaan bersamaan maksimum
Untuk melihat jumlah permintaan bersamaan saat ini, jalankan kueri Transact-SQL ini pada database Anda:
SELECT COUNT(*) AS [Concurrent_Requests]
FROM sys.dm_exec_requests R;
Untuk menganalisis beban kerja database individual, ubah kueri ini untuk memfilter pada database tertentu yang ingin Anda analisis. Misalnya, jika Anda memiliki database bernama MyDatabase
, kueri Transact-SQL ini mengembalikan jumlah permintaan bersamaan dalam database tersebut:
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';
Ini hanya rekam jepret pada satu titik waktu. Untuk lebih memahami tentang beban kerja dan persyaratan permintaan bersamaan, Anda harus mengumpulkan banyak sampel dari waktu ke waktu.
Masuk bersamaan maksimum
Anda dapat menganalisis pola pengguna dan aplikasi Anda untuk mendapatkan gambaran frekuensi login. Anda juga dapat menjalankan beban dunia nyata di lingkungan pengujian untuk memastikan bahwa Anda tidak mencapai batas ini atau batas lain yang kami bahas di artikel ini. Tidak ada satu kueri atau tampilan manajemen dinamis (DMV) yang dapat memperlihatkan jumlah atau riwayat login bersamaan.
Jika beberapa klien menggunakan string koneksi yang sama, layanan akan mengautentikasi setiap login. Jika 10 pengguna secara bersamaan terhubung ke database dengan menggunakan nama pengguna dan kata sandi yang sama, akan ada 10 login bersamaan. Batas ini hanya berlaku untuk durasi login dan autentikasi. Jika 10 pengguna yang sama tersambung ke database secara berurutan, jumlah login bersamaan tidak akan pernah lebih besar dari 1.
Sesi maksimum
Untuk melihat jumlah permintaan bersamaan, jalankan kueri T-SQL ini di database Anda:
SELECT COUNT(*) AS [Sessions]
FROM sys.dm_exec_connections;
Jika Anda menganalisis beban kerja SQL Server, ubah kueri untuk fokus pada database tertentu. Kueri ini membantu Anda menentukan kemungkinan kebutuhan sesi untuk database jika Anda mempertimbangkan untuk memindahkannya ke 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';
Sekali lagi, kueri ini mengembalikan jumlah point-in-time. Jika Anda mengumpulkan beberapa sampel dari waktu ke waktu, Anda akan memiliki pemahaman terbaik tentang penggunaan sesi Anda.
Memantau performa kueri
Kueri yang berjalan lambat atau lama penggunaan sumber daya sistemnya bersifat signifikan. Bagian ini menunjukkan cara menggunakan tampilan manajemen dinamis untuk mendeteksi beberapa masalah performa kueri umum.
Menemukan kueri N teratas
Contoh berikut mengembalikan informasi tentang lima kueri teratas yang diberi pangkat berdasarkan waktu CPU rata-rata. Contoh ini mengagregasi kueri sesuai dengan hash kuerinya, sehingga kueri yang setara secara logis dikelompokkan menurut penggunaan sumber daya kumulatifnya.
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;
Memantau kueri yang diblokir
Kueri yang berjalan lambat atau lama dapat menyebabkan penggunaan sumber daya yang berlebihan dan berakibat kueri diblokir. Penyebab pemblokiran bisa karena desain aplikasi yang buruk, rencana kueri yang buruk, kurangnya indeks yang berguna, dan sebagainya. Anda bisa menggunakan tampilan sys.dm_tran_locks untuk mendapatkan informasi tentang aktivitas penguncian saat ini dalam database. Misalnya kode, lihat sys.dm_tran_locks. Untuk informasi selengkapnya tentang pemblokiran pemecahan masalah, lihat Memahami dan mengatasi masalah pemblokiran Azure SQL.
Memantau kebuntuan
Dalam beberapa kasus, dua atau beberapa kueri dapat saling memblokir satu sama lain, mengakibatkan kebuntuan.
Anda dapat membuat Extended Events melacak database untuk menangkap peristiwa kebuntuan, lalu menemukan kueri terkait dan rencana eksekusinya di Penyimpanan Kueri.
Untuk Azure SQL Managed Instance, lihat alat Kebuntuan di panduan Kebuntuan.
Memantau rencana kueri
Rencana kueri yang tidak efisien juga dapat meningkatkan penggunaan CPU. Contoh berikut menggunakan tampilan sys.dm_exec_query_stats untuk menentukan kueri mana yang menggunakan CPU paling kumulatif.
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;
Opsi pemantauan lainnya
Memantau dengan pengamat database (pratinjau)
Pengamat database mengumpulkan data pemantauan beban kerja mendalam untuk memberi Anda tampilan terperinci tentang performa, konfigurasi, dan kesehatan database. Dasbor di portal Azure menyediakan tampilan panel kaca tunggal dari estate Azure SQL Anda dan tampilan terperinci dari setiap sumber daya yang dipantau. Data dikumpulkan ke penyimpanan data pusat di langganan Azure Anda. Anda dapat mengkueri, menganalisis, mengekspor, memvisualisasikan data yang dikumpulkan dan mengintegrasikannya dengan sistem hilir.
Untuk informasi selengkapnya tentang pengamat database, lihat artikel berikut ini:
- Memantau beban kerja Azure SQL dengan pengamat database (pratinjau)
- Mulai cepat: Membuat pengamat database untuk memantau Azure SQL (pratinjau)
- Membuat dan mengonfigurasi pengamat database (pratinjau)
- Pengumpulan data dan himpunan data pengamat database (pratinjau)
- Menganalisis data pemantauan pengamat database (pratinjau)
- Tanya Jawab Umum pengamat database
Pemantauan dengan log Azure Monitor
Azure Monitor menyediakan berbagai grup pengumpulan data diagnostik, metrik, dan titik akhir untuk memantau Azure SQL Managed Instance. Untuk informasi selengkapnya, lihat Memantau Azure SQL Managed Instance dengan Azure Monitor. Azure SQL Analytics (pratinjau) adalah integrasi dengan Azure Monitor, tempat banyak solusi pemantauan tidak lagi dalam pengembangan aktif. Untuk opsi pemantauan lainnya, lihat Pemantauan dan penyetelan performa di Azure SQL Managed Instance dan Azure SQL Database.
Lihat juga
Langkah berikutnya
- Pengenalan Azure SQL Database dan Azure SQL Managed Instance
- Menyetel aplikasi dan database untuk performa di Azure SQL Managed Instance
- Memahami dan menyelesaikan masalah pemblokiran SQL Server
- Menganalisis dan mencegah kebuntuan di Azure SQL Managed Instance
- sys.server_resource_stats (Azure SQL Managed Instance)