Analysera övervakningsdata från databasewatcher (förhandsgranskning)
gäller för:Azure SQL Database
Azure SQL Managed Instance
Förutom att använda instrumentpaneler i Azure-portaleneller skapa visualiseringar för att visa och analysera SQL-övervakningsdata i Power BI, Grafana, Azure Data Explorer eller Real-Time Analytics i Microsoft Fabrickan du köra frågor direkt mot ditt övervakningsdatalager.
Den här artikeln innehåller exempel på KQL- och T-SQL- frågor som hjälper dig att komma igång med att analysera insamlade övervakningsdata.
Använda KQL för att analysera övervakningsdata
För att analysera insamlade övervakningsdata är den rekommenderade metoden att använda Kusto Query Language (KQL). KQL är optimalt för att fråga telemetri, mått och loggar. Det ger omfattande stöd för textsökning och parsning, tidsserieoperatorer och funktioner, analys och aggregering samt många andra språkkonstruktioner som underlättar dataanalys.
KQL liknar SQL konceptuellt. Den fungerar på schemaentiteter som tabeller och kolumner och stöder relationsåtgärder som projekt, begränsa, koppla och sammanfatta, som motsvarar satserna SELECT
, JOIN
, WHERE
och GROUP BY
i SQL.
Om du vill skriva och köra KQL-frågor kan du använda antingen Kusto Explorer eller Azure Data Explorerwebbgränssnittet. Kusto Explorer är en komplett Windows-skrivbordsprogramvara, medan webbgränssnittet i Azure Data Explorer låter dig köra KQL-frågor och visualisera resultat i webbläsaren på valfri plattform.
Du kan också använda dessa verktyg för att fråga en databas i Real-Time Analytics i Microsoft Fabric. Om du vill ansluta lägger du till en ny anslutning med hjälp av Query URI- för din Real-Time Analytics-databas. Om du använder Real-Time Analytics kan du dessutom analysera övervakningsdata med hjälp av KQL-frågeuppsättningar. En KQL-frågeuppsättning kan sparas som en delbar artefakt och användas för att skapa Power BI-rapporter.
Om du är nybörjare på KQL kan följande resurser hjälpa dig att komma igång:
- Skriv din första fråga med Kusto Query Language
- snabbstart: Fråga efter exempeldata
- Självstudie: Lär dig vanliga operatorer
Följande exempel kan hjälpa dig att skriva egna KQL-frågor för att visa och analysera insamlade SQL-övervakningsdata. Du kan också använda de här exemplen som utgångspunkt när du skapar egna datavisualiseringar och instrumentpaneler.
Använda KQL för att fråga resursförbrukning över tid
I det här exemplet returnerar frågan mått för resursförbrukning (CPU, arbetare, loggskrivningsdataflöde osv.) för den primära repliken av en databas, en elastisk pool eller en SQL-hanterad instans under den senaste timmen. Förutom att returnera resultatuppsättningen visualiserar den den som ett tidsdiagram.
I det här och andra exempel ändrar du variablerna i låt-instruktioner så att de matchar namnen på dina servrar, databaser, elastiska pooler eller SQL-hanterade instanser. Om du vill använda ett annat tidsintervall ändrar du variabeln duration
. Mer information finns i tidsintervalllitteraler.
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let duration = 1h;
sqldb_database_resource_utilization
| where sample_time_utc > ago(duration)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| project sample_time_utc,
avg_cpu_percent,
avg_instance_cpu_percent,
avg_data_io_percent,
avg_log_write_percent,
max_worker_percent
| sort by sample_time_utc desc
| render timechart;
Använda KQL för att visa egenskaper för databas, elastisk pool eller SQL-hanterad instans
I det här exemplet returnerar frågan en uppsättning av alla databaser, elastiska pooler eller SQL-hanterade instanser från vilka minst ett exempel i motsvarande Egenskaperdatauppsättning samlades in under den senaste dagen. Med andra ord representerar varje rad ett övervakningsmål med de senast observerade egenskaperna.
Funktionen arg_max() aggregerar data för att returnera den senaste raden för den angivna uppsättningen kolumner som identifierar ett mål. För Azure SQL-databaser är den här uppsättningen till exempel logical_server_name
, database_name
, replica_type
.
let duration = 1d;
sqldb_database_properties
| where sample_time_utc > ago(duration)
| summarize arg_max(sample_time_utc, *) by logical_server_name, database_name, replica_type
| project-rename last_sample_time_utc = sample_time_utc
| sort by tolower(logical_server_name) asc,
tolower(database_name) asc,
case(
replica_type == "Primary", 0,
replica_type == "Geo-replication forwarder", 1,
replica_type == "Named secondary", 2,
replica_type == "HA secondary", 3,
4) asc;
Använd KQL för att visa frågekörningsstatistik
Den här frågan returnerar de vanligaste resurskrävande frågorna i din Azure SQL-egendom. Ändra en variabel för att rangordna frågor efter valfritt Query Store- mått, inklusive CPU-tid, förfluten tid, körningsantal osv. Du kan också ange variabler för att filtrera efter ett tidsintervall, frågekörningstyp och frågetext. Ange variabler för att fokusera på en specifik logisk server, elastisk pool, SQL-hanterad instans eller databas.
Frågan använder Query-körningsstatistikendatauppsättningen för att returnera antalet toppfrågor som du anger och inkluderar deras rangordning efter alla andra resursförbrukningsmått.
let topQueriesBy = "cpu_time"; // Set to one of the following metrics to return the top resource consuming queries:
// count_executions, duration, cpu_time, logical_io_reads, logical_io_writes, physical_io_reads,
// num_physical_io_reads, clr_time, dop, query_max_used_memory, rowcount, log_bytes_used, tempdb_space_used
let topQueries = 10; // Set the number of top queries to return
let endTime = now();
let startTime = endTime - 1d;
let logicalServerName = @""; // Optionally filter by logical server name
let elasticPoolName = @""; // Optionally filter by elastic pool name, if any databases are in elastic pools
let databaseName = @""; // Optionally filter by database name
let executionType = ""; // Optionally filter by execution type. Use Regular, Aborted, Exception.
let queryHash = ""; // Optionally filter by query hash (example: 0xBAAA461A6C93EA88)
let queryTextFragment = ""; // Optionally filter by a query text fragment
sqldb_database_query_runtime_stats
| where interval_start_time >= startTime and interval_end_time <= endTime
| where isempty(executionType) or execution_type_desc =~ executionType
| where isempty(logicalServerName) or logical_server_name =~ logicalServerName
| where isempty(elasticPoolName) or elastic_pool_name =~ elasticPoolName
| where isempty(databaseName) or database_name =~ databaseName
| summarize dcount_logical_servers = dcount(logical_server_name),
any_logical_server_name = take_any(logical_server_name),
dcount_elastic_pools = dcount(strcat(logical_server_name, "|", elastic_pool_name)),
any_elastic_pool_name = take_any(elastic_pool_name),
dcount_databases = dcount(strcat(logical_server_name, "|", database_name)),
any_database_name = take_any(database_name),
dcount_sql_module_name = dcount(sql_module_name),
any_sql_module_name = take_any(sql_module_name),
dcount_context_settings_id = dcount(context_settings_id),
any_context_settings_id = take_any(context_settings_id),
query_sql_text = take_any(query_sql_text),
count_executions = sum(toreal(count_executions)),
count_successful_executions = sumif(toreal(count_executions), execution_type_desc == "Regular"),
count_aborted_executions = sumif(toreal(count_executions), execution_type_desc == "Aborted"),
count_exception_executions = sumif(toreal(count_executions), execution_type_desc == "Exception"),
duration_us = sum(avg_duration_us * count_executions),
cpu_time_us = sum(avg_cpu_time_us * count_executions),
logical_io_reads = sum(avg_logical_io_reads * count_executions),
logical_io_writes = sum(avg_logical_io_writes * count_executions),
physical_io_reads = sum(avg_physical_io_reads * count_executions),
num_physical_io_reads = sum(avg_num_physical_io_reads * count_executions),
clr_time_us = sum(avg_clr_time_us * count_executions),
dop = sumif(avg_dop * count_executions, is_parallel_plan),
query_max_used_memory = sum(avg_query_max_used_memory * count_executions),
rowcount = sum(avg_rowcount * count_executions),
log_bytes_used = sum(avg_log_bytes_used * count_executions),
tempdb_space_used = sum(avg_tempdb_space_used * count_executions)
by query_hash
| project logical_server_name = iif(dcount_logical_servers == 1, any_logical_server_name, strcat(any_logical_server_name, " (+", tostring(dcount_logical_servers - 1), ")")),
elastic_pool_name = iif(dcount_elastic_pools == 1, any_elastic_pool_name, strcat(any_elastic_pool_name, " (+", tostring(dcount_elastic_pools - 1), ")")),
database_name = iif(dcount_databases == 1, any_database_name, strcat(any_database_name, " (+", tostring(dcount_databases - 1), ")")),
query_sql_text,
count_executions,
count_successful_executions,
count_aborted_executions,
count_exception_executions,
duration_us,
cpu_time_us,
logical_io_reads,
logical_io_writes,
physical_io_reads,
num_physical_io_reads,
clr_time_us,
dop,
query_max_used_memory_kb = query_max_used_memory * 8,
rowcount,
log_bytes_used,
tempdb_space_used_kb = tempdb_space_used * 8,
sql_module_name = iif(dcount_sql_module_name == 1, any_sql_module_name, strcat(any_sql_module_name, " (+", tostring(dcount_sql_module_name - 1), ")")),
context_settings_id = iif(dcount_context_settings_id == 1, tostring(any_context_settings_id), strcat(any_context_settings_id, " (+", tostring(dcount_context_settings_id - 1), ")")),
query_hash
| sort by count_executions desc | extend count_executions_rank = row_rank_dense(count_executions)
| sort by duration_us desc | extend duration_rank = row_rank_dense(duration_us)
| sort by cpu_time_us desc | extend cpu_time_rank = row_rank_dense(cpu_time_us)
| sort by logical_io_reads desc | extend logical_io_reads_rank = row_rank_dense(logical_io_reads)
| sort by logical_io_writes desc | extend logical_io_writes_rank = row_rank_dense(logical_io_writes)
| sort by physical_io_reads desc | extend physical_io_reads_rank = row_rank_dense(physical_io_reads)
| sort by num_physical_io_reads desc | extend num_physical_io_reads_rank = row_rank_dense(num_physical_io_reads)
| sort by clr_time_us desc | extend clr_time_rank = row_rank_dense(clr_time_us)
| sort by dop desc | extend dop_rank = row_rank_dense(dop)
| sort by query_max_used_memory_kb desc | extend query_max_used_memory_rank = row_rank_dense(query_max_used_memory_kb)
| sort by rowcount desc | extend rowcount_rank = row_rank_dense(rowcount)
| sort by log_bytes_used desc | extend log_bytes_used_rank = row_rank_dense(log_bytes_used)
| sort by tempdb_space_used_kb desc | extend tempdb_space_used_rank = row_rank_dense(tempdb_space_used_kb)
| sort by case(
topQueriesBy =~ "count_executions", toreal(count_executions),
topQueriesBy =~ "duration", toreal(duration_us),
topQueriesBy =~ "cpu_time", toreal(cpu_time_us),
topQueriesBy =~ "logical_io_reads", toreal(logical_io_reads),
topQueriesBy =~ "logical_io_writes", toreal(logical_io_writes),
topQueriesBy =~ "physical_io_reads", toreal(physical_io_reads),
topQueriesBy =~ "num_physical_io_reads", toreal(num_physical_io_reads),
topQueriesBy =~ "clr_time", toreal(clr_time_us),
topQueriesBy =~ "dop", toreal(dop),
topQueriesBy =~ "query_max_used_memory", toreal(query_max_used_memory_kb),
topQueriesBy =~ "rowcount", toreal(rowcount),
topQueriesBy =~ "log_bytes_used", toreal(log_bytes_used),
topQueriesBy =~ "tempdb_space_used", toreal(tempdb_space_used_kb),
real(null)
) desc,
count_executions desc
| project-away count_executions
| where isempty(queryHash) or query_hash == queryHash
| where isempty(queryTextFragment) or query_sql_text contains queryTextFragment
| take topQueries;
Använda KQL för att analysera prestandaräknare över tid
I det här exemplet returnerar frågan prestandaräknarevärden för ett tidsintervall som startar 30 minuter före den angivna sluttiden.
I det här exemplet används kumulativa prestandaräknare som Total request count
och Query optimizations/sec
. Kumulativ innebär att räknarvärdet fortsätter att öka när SQL-frågeaktiviteten inträffar. Frågan i det här exemplet beräknar skillnaden, eller deltat, mellan räknarvärdet i varje exempel och dess värde i föregående exempel för att hämta antalet begäranden och optimeringar som inträffat sedan föregående exempel och visualiserar sedan dessa mått i ett tidsdiagram.
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let endTime = datetime("2023-12-19 22:10:00");
let startTime = endTime - 30m;
sqldb_database_performance_counters_common
| where sample_time_utc between (startTime .. endTime)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| where cntr_type == 272696576 // restrict to cumulative counters
| where object_name =~ "Workload Group Stats" and counter_name in ("Total request count","Query optimizations/sec")
| project replica_id, sample_time_utc, object_name, counter_name, cntr_value
| sort by replica_id asc, counter_name asc, sample_time_utc asc
| extend delta_cntr_value = iif(cntr_value >= prev(cntr_value) and counter_name == prev(counter_name) and replica_id == prev(replica_id), cntr_value - prev(cntr_value), real(null)),
delta_sample_time_utc = iif(sample_time_utc >= prev(sample_time_utc), datetime_diff("Millisecond", sample_time_utc, prev(sample_time_utc)), long(null))
| where isnotempty(delta_sample_time_utc)
| extend value = delta_cntr_value / delta_sample_time_utc * 1000
| summarize requests_per_sec = take_anyif(value, counter_name =~ "Total request count"),
query_optimizations_per_sec = take_anyif(value, counter_name =~ "Query optimizations/sec")
by sample_time_utc
| sort by sample_time_utc desc
| project sample_time_utc, requests_per_sec, query_optimizations_per_sec
| render timechart;
Följande exempel är för prestandaräknare för tidpunkter som rapporterar det senast observerade värdet, till exempel Active memory grants count
, Pending memory grants count
och Processes blocked
. Tidsintervallet är de senaste 30 minuterna.
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let duration = 30m;
sqldb_database_performance_counters_common
| where sample_time_utc > ago(duration)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| where cntr_type == 65792 // restrict to point-in-time counters
| where (object_name =~ "General Statistics" and counter_name in ("Processes blocked"))
or
(object_name =~ "Resource Pool Stats" and counter_name in ("Active memory grants count","Pending memory grants count"))
| project sample_time_utc, counter_name, cntr_value
| render timechart;
I följande exempel används prestandaräknare (detaljerad) datauppsättning för att kartlägga PROCESSORanvändning för användar- och interna resurspooler och arbetsbelastningsgrupper i Azure SQL Database. Mer information finns i Resursförbrukning efter användararbetsbelastningar och interna processer.
Användararbetsbelastningarna körs i SloSharedPool1
eller UserPool
resurspooler, medan alla andra resurspooler används för olika systemarbetsbelastningar.
På samma sätt körs användararbetsbelastningarna i arbetsbelastningsgrupperna med namnet från och med UserPrimaryGroup.DBId
, medan alla andra arbetsbelastningsgrupper används för olika systemarbetsbelastningar. Till exempel körs övervakningsfrågor för databasövervakning i arbetsbelastningsgruppen SQLExternalMonitoringGroup
.
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let endTime = datetime("2023-12-19 22:10:00");
let startTime = endTime - 30m;
sqldb_database_performance_counters_detailed
| where sample_time_utc between (startTime .. endTime)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| where cntr_type == 537003264 // restrict to ratio percentage counters
| where object_name =~ "Resource Pool Stats" and counter_name in ("CPU usage %")
| project sample_time_utc, resource_pool = instance_name, cpu_percentage = cntr_value
| render timechart;
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let endTime = datetime("2023-12-19 22:10:00");
let startTime = endTime - 30m;
sqldb_database_performance_counters_detailed
| where sample_time_utc between (startTime .. endTime)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| where cntr_type == 537003264 // restrict to ratio percentage counters
| where object_name =~ "Workload Group Stats" and counter_name in ("CPU usage %")
| project sample_time_utc, workload_group = instance_name, cpu_percentage = cntr_value
| render timechart;
Använda KQL för att analysera kumulativa väntetider över tid
Det här exemplet visar hur du kartlägger de vanligaste SQL-väntetyperna under ett tidsintervall. Frågan beräknar den kumulativa väntetiden för varje väntetyp, i millisekunder per sekund efter förfluten tid. Du kan justera frågevariabler för att ange intervallets start- och sluttid, antalet vanligaste väntetyper som ska inkluderas och steget mellan datapunkterna i diagrammet.
Frågan använder två tekniker för att förbättra prestandan:
- Den partitionen KQL-operatorn med
shuffle
strategi för att sprida frågebearbetning över flera klusternoder, om den finns. - Funktionen materialize() för att bevara en mellanliggande resultatuppsättning som återanvänds för att beräkna de högsta väntetiderna och för att skapa tidsserierna som ska kartläggas.
let logicalServer = @"your-server-name";
let databaseName = @"your-database-name";
let replicaType = "Primary";
let endTime = datetime("2023-12-19 22:10:00");
let startTime = endTime - 30m;
let top_wait_types = 10;
let chart_step = 30s;
let wait_type_sample = materialize (
sqldb_database_wait_stats
| where sample_time_utc between (startTime .. endTime)
| where logical_server_name =~ logicalServer
| where database_name =~ databaseName
| where replica_type =~ replicaType
| project replica_id, sample_time_utc, wait_type, wait_time_ms
| partition hint.strategy=shuffle by wait_type
(
sort by replica_id asc, sample_time_utc asc
| extend delta_wait_time_ms = iif(wait_time_ms >= prev(wait_time_ms) and replica_id == prev(replica_id), wait_time_ms - prev(wait_time_ms), long(null)),
delta_sample_time_utc = iif(sample_time_utc >= prev(sample_time_utc), datetime_diff("Millisecond", sample_time_utc, prev(sample_time_utc)), long(null))
| where isnotempty(delta_sample_time_utc)
| extend wait_ms_per_s = toreal(delta_wait_time_ms) / delta_sample_time_utc * 1000
| project sample_time_utc, wait_type, wait_ms_per_s
)
);
let top_wait = (
wait_type_sample
| summarize total_wait_ms_per_s = sum(wait_ms_per_s) by wait_type
| top top_wait_types by total_wait_ms_per_s desc
| project-away total_wait_ms_per_s
);
wait_type_sample
| join kind=inner top_wait on wait_type
| project-away wait_type1
| make-series wait_ms_per_s = avgif(wait_ms_per_s, isfinite(wait_ms_per_s)) default = long(null) on sample_time_utc from startTime to endTime step chart_step by wait_type
| project wait_type, sample_time_utc, wait_ms_per_s
| render timechart;
Använda T-SQL för att analysera övervakningsdata
Om du redan är bekant med T-SQL kan du börja fråga och analysera SQL-övervakningsdata direkt utan att behöva lära dig KQL. Men KQL- är det rekommenderade språket för att fråga efter data i Azure Data Explorer eller Real-Time Analytics eftersom det ger oöverträffad support för att fråga telemetridata.
Du kan ansluta till din Azure Data Explorer eller Real-Time Analytics-databas från SQL Server Management Studio (SSMS), från Visual Studio Code med SQL server mssql-tillägget, och från andra vanliga verktyg. Du kan fråga en Azure Data Explorer eller en KQL-databas som om det vore en SQL Server eller en Azure SQL-databas. Mer information finns i Frågedata i Azure Data Explorer med SQL Server-emulering.
Not
Alla T-SQL-konstruktioner stöds inte i Azure Data Explorer och Real-Time Analytics. Mer information finns i Fråga efter data med T-SQL.
Fuskbladet SQL till Kusto Query Language kan hjälpa dig att översätta dina T-SQL-frågor till KQL om du upptäcker att T-SQL-stödet inte är tillräckligt för dina behov, eller om du vill konvertera dina T-SQL-frågor till KQL för att använda dess avancerade analysfunktioner.
I följande exempel visas hur du frågar efter övervakningsdata i databasbevakarens datalager med hjälp av T-SQL.
Använda T-SQL för att analysera resursförbrukning över tid
I det här exemplet returnerar frågan mått för resursförbrukning (CPU, arbetare, loggskrivningsdataflöde osv.) för den primära repliken av en databas, en elastisk pool eller en SQL-hanterad instans under den senaste timmen.
I det här och andra exempel ändrar du variablerna i DECLARE
-instruktionen så att de matchar namnen på din server, databas, elastiska pool eller SQL-hanterade instans.
DECLARE @LogicalServerName sysname = 'your-server-name',
@DatabaseName sysname = 'your-database-name',
@ReplicaType sysname = 'Primary',
@DurationMinutes int = 60;
SELECT sample_time_utc,
avg_cpu_percent,
avg_instance_cpu_percent,
avg_data_io_percent,
avg_log_write_percent,
max_worker_percent
FROM sqldb_database_resource_utilization
WHERE sample_time_utc > DATEADD(minute, -@DurationMinutes, SYSUTCDATETIME())
AND
logical_server_name = @LogicalServerName
AND
database_name = @DatabaseName
AND
replica_type = @ReplicaType
ORDER BY sample_time_utc DESC;
Använda T-SQL för att visa egenskaper för databas, elastisk pool eller SQL-hanterad instans
I det här exemplet returnerar frågan en uppsättning alla databaser, elastiska pooler eller SQL-hanterade instanser från vilka minst ett exempel i motsvarande Egenskaperdatauppsättning har samlats in under de senaste 24 timmarna. Med andra ord representerar varje rad ett övervakningsmål med de senast observerade egenskaperna.
DECLARE @DurationHours int = 24;
SELECT p.sample_time_utc,
p.logical_server_name,
p.database_name,
p.replica_type,
p.database_id,
p.elastic_pool_name,
p.service_tier,
p.service_level_objective,
p.logical_cpu_count,
p.database_engine_memory_mb,
p.compatibility_level,
p.updateability,
p.database_engine_build_time,
p.database_engine_start_time_utc
FROM sqldb_database_properties AS p
INNER JOIN (
SELECT logical_server_name,
database_name,
replica_type,
MAX(sample_time_utc) AS last_sample_time_utc
FROM sqldb_database_properties
WHERE sample_time_utc > DATEADD(hour, -@DurationHours, SYSUTCDATETIME())
GROUP BY logical_server_name,
database_name,
replica_type
) AS ls
ON p.logical_server_name = ls.logical_server_name
AND
p.database_name = ls.database_name
AND
p.replica_type = ls.replica_type
AND
p.sample_time_utc = ls.last_sample_time_utc
WHERE p.sample_time_utc > DATEADD(hour, -@DurationHours, SYSUTCDATETIME())
ORDER BY LOWER(logical_server_name) ASC,
LOWER(database_name) ASC,
CASE replica_type
WHEN 'Primary' THEN 0
WHEN 'Geo-replication forwarder' THEN 1
WHEN 'Named secondary' THEN 2
WHEN 'HA secondary' THEN 3
END ASC;
Använd T-SQL för att visa frågekörningsstatistik
Den här frågan returnerar de vanligaste resurskrävande frågorna i din Azure SQL-egendom. Ändra variabeln @TopQueriesBy
för att hitta de vanligaste frågorna efter valfritt Query Store- mått, inklusive CPU-tid, förfluten tid, körningsantal osv. Du kan också ange variabler för att filtrera efter ett tidsintervall, frågekörningstyp och frågehash för en specifik fråga, eller för att fokusera på databaser från en specifik logisk server, elastisk pool eller SQL-hanterad instans.
Frågan använder fråge-runtime-statistik från datasetet för att returnera de högst rankade frågorna du specificerar. Den returnerar också deras rangordning efter alla andra mått för resursförbrukning.
DECLARE @EndTime datetime2 = SYSUTCDATETIME(),
@StartTime datetime2 = DATEADD(hour, -24, SYSUTCDATETIME()),
/*
Set the next variable to one of the following metrics to return the top resource consuming queries:
executions, cpu_time, duration, logical_io_reads, physical_io_reads, num_physical_io_reads,
clr_time, query_max_used_memory, log_bytes_used, tempdb_space_used, row_count, dop
*/
@TopQueriesBy varchar(30) = 'cpu_time',
@TopQueries int = 10,
@LogicalServerName sysname = '', -- Optionally filter by logical server name
@ElasticPoolName sysname = '', -- Optionally filter by elastic pool name, if any databases are in elastic pools
@DatabaseName sysname = '', -- Optionally filter by database name
@ExecutionType varchar(30) = '', -- Optionally filter by execution type. Use Regular, Aborted, Exception.
@QueryHash varchar(18) = ''; -- Optionally filter by query hash (example: 0xBAAA461A6C93EA88)
SELECT TOP (@TopQueries)
CONCAT(logical_server_name, IIF(count_logical_servers > 1, CONCAT(' (+', CAST(count_logical_servers - 1 AS varchar(11)), ')'), '')) AS logical_server_name,
CONCAT(database_name, IIF(count_databases > 1, CONCAT(' (+', CAST(count_databases - 1 AS varchar(11)), ')'), '')) AS database_name,
query_sql_text,
CONCAT(CAST(query_id AS varchar(11)), IIF(count_queries > 1, CONCAT(' (+', CAST(count_queries - 1 AS varchar(11)), ')'), '')) AS query_id,
CONCAT(CAST(plan_id AS varchar(11)), IIF(count_plans > 1, CONCAT(' (+', CAST(count_plans - 1 AS varchar(11)), ')'), '')) AS plan_id,
regular_executions,
aborted_executions,
exception_executions,
cpu_time_us,
duration_us,
logical_io_reads,
physical_io_reads,
num_physical_io_reads,
clr_time_us,
query_max_used_memory_kb,
log_bytes_used,
tempdb_space_used_kb,
row_count,
dop,
query_hash,
executions_rank,
cpu_time_rank,
duration_rank,
logical_io_reads_rank,
physical_io_reads_rank,
num_physical_io_reads_rank,
clr_time_rank,
query_max_used_memory_rank,
log_bytes_used_rank,
tempdb_space_used_rank,
row_count_rank,
dop_rank
FROM (
SELECT *,
DENSE_RANK() OVER (ORDER BY executions DESC) AS executions_rank,
DENSE_RANK() OVER (ORDER BY cpu_time_us DESC) AS cpu_time_rank,
DENSE_RANK() OVER (ORDER BY duration_us DESC) AS duration_rank,
DENSE_RANK() OVER (ORDER BY logical_io_reads DESC) AS logical_io_reads_rank,
DENSE_RANK() OVER (ORDER BY physical_io_reads DESC) AS physical_io_reads_rank,
DENSE_RANK() OVER (ORDER BY num_physical_io_reads DESC) AS num_physical_io_reads_rank,
DENSE_RANK() OVER (ORDER BY clr_time_us DESC) AS clr_time_rank,
DENSE_RANK() OVER (ORDER BY query_max_used_memory_kb DESC) AS query_max_used_memory_rank,
DENSE_RANK() OVER (ORDER BY log_bytes_used DESC) AS log_bytes_used_rank,
DENSE_RANK() OVER (ORDER BY tempdb_space_used_kb DESC) AS tempdb_space_used_rank,
DENSE_RANK() OVER (ORDER BY row_count DESC) AS row_count_rank,
DENSE_RANK() OVER (ORDER BY dop DESC) AS dop_rank
FROM (
SELECT query_hash,
COUNT(DISTINCT(logical_server_name)) AS count_logical_servers,
MAX(logical_server_name) AS logical_server_name,
COUNT(DISTINCT(database_name)) AS count_databases,
MAX(database_name) AS database_name,
COUNT(DISTINCT(query_id)) AS count_queries,
MAX(query_id) AS query_id,
COUNT(DISTINCT(plan_id)) AS count_plans,
MAX(plan_id) AS plan_id,
MAX(query_sql_text) AS query_sql_text,
SUM(IIF(execution_type_desc = 'Regular', count_executions, 0)) AS regular_executions,
SUM(IIF(execution_type_desc = 'Aborted', count_executions, 0)) AS aborted_executions,
SUM(IIF(execution_type_desc = 'Exception', count_executions, 0)) AS exception_executions,
SUM(count_executions) AS executions,
SUM(avg_cpu_time_us * count_executions) AS cpu_time_us,
SUM(avg_duration_us * count_executions) AS duration_us,
SUM(avg_logical_io_reads * count_executions) AS logical_io_reads,
SUM(avg_physical_io_reads * count_executions) AS physical_io_reads,
SUM(avg_num_physical_io_reads * count_executions) AS num_physical_io_reads,
SUM(avg_clr_time_us * count_executions) AS clr_time_us,
SUM(avg_query_max_used_memory * count_executions) * 8 AS query_max_used_memory_kb,
SUM(avg_log_bytes_used * count_executions) AS log_bytes_used,
SUM(avg_tempdb_space_used * count_executions) * 8 AS tempdb_space_used_kb,
SUM(avg_rowcount * count_executions) AS row_count,
SUM(IIF(is_parallel_plan = 1, avg_dop * count_executions, NULL)) AS dop
FROM sqldb_database_query_runtime_stats
WHERE interval_start_time >= @StartTime AND interval_end_time <= @EndTime
AND
(@ExecutionType = '' OR LOWER(execution_type_desc) = LOWER(@ExecutionType))
AND
(@LogicalServerName = '' OR LOWER(logical_server_name) = LOWER(@LogicalServerName))
AND
(@ElasticPoolName = '' OR LOWER(elastic_pool_name) = LOWER(@ElasticPoolName))
AND
(@DatabaseName = '' OR LOWER(database_name) = LOWER(@DatabaseName))
GROUP BY query_hash
) AS rsa
) AS rsar
WHERE @QueryHash = '' OR LOWER(query_hash) = LOWER(@QueryHash)
ORDER BY CASE @TopQueriesBy
WHEN 'executions' THEN executions_rank
WHEN 'cpu_time' THEN cpu_time_rank
WHEN 'duration' THEN duration_rank
WHEN 'logical_io_reads' THEN logical_io_reads_rank
WHEN 'physical_io_reads' THEN physical_io_reads_rank
WHEN 'num_physical_io_reads' THEN num_physical_io_reads_rank
WHEN 'clr_time' THEN clr_time_rank
WHEN 'query_max_used_memory' THEN query_max_used_memory_rank
WHEN 'log_bytes_used' THEN log_bytes_used_rank
WHEN 'tempdb_space_used' THEN tempdb_space_used_rank
WHEN 'row_count' THEN row_count_rank
WHEN 'dop' THEN dop_rank
END ASC;
Använda T-SQL för att analysera prestandaräknare över tid
I det här exemplet returnerar frågan prestandaräknarvärden för de senaste 30 minuterna.
I det här exemplet används kumulativa prestandaräknare som Total request count
och Query optimizations/sec
. Kumulativ innebär att värdet i räknaren fortsätter att öka när frågeaktivitet sker. Frågan använder LAG() analysfunktion för att beräkna skillnaden, eller delta, mellan räknarvärdet i varje exempel och dess värde i föregående exempel för att hämta antalet begäranden och optimeringar som inträffat sedan föregående exempel.
DECLARE @LogicalServerName sysname = 'your-server-name',
@DatabaseName sysname = 'your-database-name',
@ReplicaType sysname = 'Primary',
@DurationMinutes int = 30;
SELECT sample_time_utc,
SUM(IIF(
counter_name = 'Total request count',
CAST((cntr_value - prev_cntr_value) AS decimal) / DATEDIFF(millisecond, prev_sample_time_utc, sample_time_utc) * 1000,
NULL
)) AS requests_per_second,
SUM(IIF(
counter_name = 'Query optimizations/sec',
CAST((cntr_value - prev_cntr_value) AS decimal) / DATEDIFF(millisecond, prev_sample_time_utc, sample_time_utc) * 1000,
NULL
)) AS query_optimizations_per_second
FROM (
SELECT sample_time_utc,
LAG(sample_time_utc) OVER (PARTITION BY replica_id, object_name, counter_name ORDER BY sample_time_utc ASC) AS prev_sample_time_utc,
counter_name,
cntr_value,
LAG(cntr_value) OVER (PARTITION BY replica_id, object_name, counter_name ORDER BY sample_time_utc ASC) AS prev_cntr_value
FROM sqldb_database_performance_counters_common
WHERE sample_time_utc > DATEADD(minute, -@DurationMinutes, SYSUTCDATETIME())
AND
logical_server_name = @LogicalServerName
AND
database_name = @DatabaseName
AND
replica_type = @ReplicaType
AND
cntr_type = 272696576 /* restrict to cumulative counters */
AND
object_name = 'Workload Group Stats'
AND
counter_name IN ('Total request count','Query optimizations/sec')
) AS pc
WHERE cntr_value >= prev_cntr_value
AND
sample_time_utc >= prev_sample_time_utc
GROUP BY sample_time_utc
ORDER BY sample_time_utc DESC;
Använd T-SQL för att analysera prestandaräknare vid en given tidpunkt
Nästa exempel är för prestandaräknare för tidpunkter som rapporterar det senast observerade värdet, till exempel Active memory grants count
, Pending memory grants count
och Processes blocked
.
DECLARE @LogicalServerName sysname = 'your-server-name',
@DatabaseName sysname = 'your-database-name',
@ReplicaType sysname = 'Primary',
@DurationMinutes int = 30;
SELECT sample_time_utc,
SUM(IIF(
counter_name = 'Processes blocked',
cntr_value,
NULL
)) AS processes_blocked,
SUM(IIF(
counter_name = 'Active memory grants count',
cntr_value,
NULL
)) AS active_memory_grants,
SUM(IIF(
counter_name = 'Pending memory grants count',
cntr_value,
NULL
)) AS pending_memory_grants
FROM (
SELECT sample_time_utc,
counter_name,
cntr_value
FROM sqldb_database_performance_counters_common
WHERE sample_time_utc > DATEADD(minute, -@DurationMinutes, SYSUTCDATETIME())
AND
logical_server_name = @LogicalServerName
AND
database_name = @DatabaseName
AND
replica_type = @ReplicaType
AND
cntr_type = 65792 /* restrict to point-in-time counters */
AND
(
(object_name = 'General Statistics' AND counter_name IN ('Processes blocked'))
OR
(object_name = 'Resource Pool Stats' AND counter_name IN ('Active memory grants count','Pending memory grants count'))
)
) AS pc
GROUP BY sample_time_utc
ORDER BY sample_time_utc DESC;
Använda T-SQL för att analysera kumulativa väntetider över tid
I det här exemplet returnerar frågan de 10 vanligaste väntetyperna med den genomsnittliga kumulativa väntetiden under ett 30-minutersintervall. Kumulativ innebär att frågan beräknar den totala tiden, i millisekunder, som tillbringas under varje väntetyp av alla begäranden i varje sekund. Eftersom flera begäranden kan köras (och vänta) samtidigt kan den kumulativa väntetiden i varje sekund vara mer än en sekund.
DECLARE @LogicalServerName sysname = 'your-server-name',
@DatabaseName sysname = 'your-database-name',
@ReplicaType sysname = 'Primary',
@DurationMinutes int = 30;
SELECT TOP (10) wait_type,
SUM(CAST((wait_time_ms - prev_wait_time_ms) AS decimal)) * 1000
/
SUM(DATEDIFF(millisecond, prev_sample_time_utc, sample_time_utc))
AS wait_time_ms_per_sec
FROM (
SELECT sample_time_utc,
LAG(sample_time_utc) OVER (PARTITION BY replica_id, wait_type ORDER BY sample_time_utc ASC) AS prev_sample_time_utc,
wait_type,
wait_time_ms,
LAG(wait_time_ms) OVER (PARTITION BY replica_id, wait_type ORDER BY sample_time_utc ASC) AS prev_wait_time_ms
FROM sqldb_database_wait_stats
WHERE sample_time_utc > DATEADD(minute, -@DurationMinutes, SYSUTCDATETIME())
AND
logical_server_name = @LogicalServerName
AND
database_name = @DatabaseName
AND
replica_type = @ReplicaType
) AS w
WHERE sample_time_utc >= prev_sample_time_utc
AND
wait_time_ms >= prev_wait_time_ms
GROUP BY wait_type
ORDER BY wait_time_ms_per_sec DESC;
Relaterat innehåll
- Övervaka Azure SQL-arbetsbelastningar med databasövervakare (förhandsversion)
- snabbstart: Skapa en databasövervakare för att övervaka Azure SQL (förhandsversion)
- Skapa och konfigurera en databasskådare (förhandsversion)
- Database Watcher-aviseringar (förhandsversion)
- Vanliga frågor och svar om Database Watcher
- Utbildningsresurser för Kusto Query Language