Analýza dat monitorování sledovacího procesu databáze (Preview)
Platí pro: Azure SQL Database Azure SQL Managed Instance
Kromě použití řídicích panelů na webu Azure Portal nebo vytváření vizualizací pro zobrazení a analýzu dat monitorování SQL v Power BI, Grafana, Azure Data Exploreru nebo Analýzách v reálném čase v Microsoft Fabric můžete dotazovat přímo do úložiště dat monitorování.
Tento článek obsahuje příklady dotazů KQL a T-SQL , které vám pomůžou začít s analýzou shromážděných dat monitorování.
Analýza dat monitorování pomocí KQL
K analýze shromážděných dat monitorování se doporučuje použít dotazovací jazyk Kusto (KQL). KQL je optimální pro dotazování telemetrie, metrik a protokolů. Poskytuje rozsáhlou podporu pro vyhledávání a analýzu textu, operátory a funkce časových řad, analýzy a agregace a mnoho dalších konstruktorů jazyka, které usnadňují analýzu dat.
Jazyk KQL je koncepčně podobný jazyku SQL. Pracuje s entitami schématu, jako jsou tabulky a sloupce, a podporuje relační operace, jako je projekt, omezení, spojení a shrnutí, odpovídající SELECT
klauzuli , JOIN
, WHERE
a GROUP BY
klauzule v SQL.
K psaní a spouštění dotazů KQL můžete použít Buď Průzkumník Kusto, nebo webové uživatelské rozhraní Azure Data Exploreru. Kusto Explorer je plnohodnotný desktopový software pro Windows, zatímco webové uživatelské rozhraní Azure Data Exploreru umožňuje spouštět dotazy KQL a vizualizovat výsledky v prohlížeči na libovolné platformě.
Tyto nástroje můžete také použít k dotazování databáze v analýzách v reálném čase v Microsoft Fabric. Pokud se chcete připojit, přidejte nové připojení pomocí identifikátoru URI dotazu databáze Analýzy v reálném čase. Kromě toho, pokud používáte analýzu v reálném čase, můžete analyzovat data monitorování pomocí sad dotazů KQL. Sadu dotazů KQL je možné uložit jako artefakt prostředků infrastruktury pro sdílení a použít k vytváření sestav Power BI.
Pokud s jazykem KQL začínáte, můžou vám s tím pomoct následující zdroje informací:
- Napsání prvního dotazu pomocí dotazovací jazyk Kusto
- Rychlý start: Dotazování ukázkových dat
- Kurz: Seznámení s běžnými operátory
Následující příklady vám můžou pomoct psát vlastní dotazy KQL pro zobrazení a analýzu shromážděných dat monitorování SQL. Tyto příklady můžete použít také jako výchozí bod při vytváření vlastních vizualizací dat a řídicích panelů.
Použití KQL k dotazování spotřeby prostředků v průběhu času
V tomto příkladu dotaz vrátí metriky spotřeby prostředků (procesor, pracovní procesy, propustnost zápisu protokolu atd.) pro primární repliku databáze, elastický fond nebo spravovanou instanci SQL za poslední hodinu. Kromě vrácení sady výsledků ji vizualizuje jako časový graf.
V tomto a dalších příkladech změňte proměnné v příkazech let tak, aby odpovídaly názvům vašeho serveru, databáze, elastického fondu nebo spravované instance SQL. Pokud chcete použít jiný časový interval, změňte proměnnou duration
. Další informace najdete v literálech časových rozsahů.
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;
Použití KQL k zobrazení vlastností databáze, elastického fondu nebo spravované instance SQL
V tomto příkladu dotaz vrátí sadu všech databází, elastických fondů nebo spravovaných instancí SQL, ze kterých se během posledního dne shromáždila alespoň jedna ukázka v odpovídající datové sadě Vlastností. Jinými slovy, každý řádek představuje cíl monitorování s jeho naposledy pozorovanými vlastnostmi.
Funkce arg_max() agreguje data, aby vrátila nejnovější řádek pro zadanou sadu sloupců, které identifikují cíl. Například pro databáze Azure SQL je tato sada 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;
Zobrazení statistik modulu runtime dotazu pomocí KQL
Tento dotaz vrátí dotazy s nejvyšším využitím prostředků ve vašich aktivech Azure SQL. Změňte proměnnou na pořadí dotazů podle libovolné metriky úložiště dotazů, včetně času procesoru, uplynulého času, počtu spuštění atd. Můžete také nastavit proměnné pro filtrování podle časového intervalu, typu spuštění dotazu a textu dotazu. Nastavte proměnné tak, aby se zaměřovaly na konkrétní logický server, elastický fond, spravovanou instanci SQL nebo databázi.
Dotaz používá datovou sadu statistik modulu runtime dotazu k vrácení počtu zadaných nejčastějších dotazů a jejich hodnocení podle metriky spotřeby všech ostatních prostředků.
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;
Analýza čítačů výkonu v průběhu času pomocí KQL
V tomto příkladu dotaz vrátí hodnoty čítače výkonu pro časový interval, který začíná 30 minut před zadaným koncovým časem.
Tento příklad používá kumulativní čítače výkonu, například Total request count
a Query optimizations/sec
. Kumulativní znamená, že hodnota čítače se neustále zvyšuje, protože dochází k aktivitě dotazů SQL. Dotaz v tomto příkladu vypočítá rozdíl nebo rozdíl mezi hodnotou čítače v každé ukázce a její hodnotou v předchozí ukázce, aby získal počet požadavků a optimalizací, ke kterým došlo od předchozí ukázky, a pak tyto metriky vizualizuje v časovém grafu.
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;
Následující příklad je určen pro čítače výkonu k určitému bodu v čase, které hlásí naposledy pozorovanou hodnotu, například Active memory grants count
, Pending memory grants count
a Processes blocked
. Časový interval je posledních 30 minut.
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;
Následující příklad používá čítače výkonu (podrobnou) datovou sadu k grafu využití procesoru pro uživatelské a interní fondy prostředků a skupiny úloh ve službě Azure SQL Database. Další informace najdete v tématu Využití prostředků podle uživatelských úloh a interních procesů.
Uživatelské úlohy běží v fondech SloSharedPool1
zdrojů nebo UserPool
ve fondech zdrojů, zatímco všechny ostatní fondy zdrojů se používají pro různé systémové úlohy.
Podobně jsou uživatelské úlohy spuštěné ve skupinách úloh pojmenovaných počínaje UserPrimaryGroup.DBId
, zatímco všechny ostatní skupiny úloh se používají pro různé systémové úlohy. Například sledovací dotazy sledovacího procesů databáze jsou spuštěné ve SQLExternalMonitoringGroup
skupině úloh.
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;
Použití KQL k analýze kumulativních čekání v průběhu času
Tento příklad ukazuje, jak v průběhu časového intervalu namapovat hlavní typy čekání SQL. Dotaz vypočítá kumulativní dobu čekání pro každý typ čekání v milisekundách za sekundu uplynulého času. Proměnné dotazu můžete upravit tak, aby nastavily počáteční a koncový čas intervalu, počet hlavních typů čekání, které se mají zahrnout, a krok mezi datovými body v grafu.
Dotaz používá ke zlepšení výkonu dvě techniky:
- Operátor KQL oddílu
shuffle
se strategií rozložení zpracování dotazů na několik uzlů clusteru( pokud je k dispozici). - Funkce materialize() pro zachování přechodné sady výsledků, která se znovu použije pro výpočet horních čekání a vytvoření časové řady, která se má vymapovat.
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;
Analýza dat monitorování pomocí T-SQL
Pokud už znáte T-SQL, můžete hned začít dotazovat a analyzovat data monitorování SQL, aniž byste se museli učit KQL. KQL je však doporučený jazyk pro dotazování dat v Azure Data Exploreru nebo analýzách v reálném čase, protože poskytuje jedinečnou podporu pro dotazování telemetrických dat.
K Azure Data Exploreru nebo databázi Analýzy v reálném čase se můžete připojit z APLIKACE SQL Server Management Studio (SSMS), Azure Data Studia a dalších běžných nástrojů. Můžete dotazovat Azure Data Explorer nebo databázi KQL, jako by šlo o SQL Server nebo databázi Azure SQL. Další informace najdete v tématu Dotazování dat v Azure Data Exploreru pomocí emulace SQL Serveru.
Poznámka:
Ne každý konstruktor T-SQL se podporuje v Azure Data Exploreru a analýze v reálném čase. Podrobnosti najdete v tématu Dotazování dat pomocí T-SQL.
Tahák SQL pro dotazovací jazyk Kusto vám může pomoct přeložit dotazy T-SQL na KQL, pokud zjistíte, že podpora T-SQL není dostatečná pro vaše potřeby, nebo pokud chcete převést dotazy T-SQL na KQL, aby používaly jeho pokročilé analytické funkce.
Následující příklady ukazují, jak dotazovat data monitorování v úložišti dat sledovacího nástroje databáze pomocí T-SQL.
Použití T-SQL k analýze spotřeby prostředků v průběhu času
V tomto příkladu dotaz vrátí metriky spotřeby prostředků (procesor, pracovní procesy, propustnost zápisu protokolu atd.) pro primární repliku databáze, elastický fond nebo spravovanou instanci SQL za poslední hodinu.
V tomto a dalších příkladech změňte proměnné v DECLARE
příkazu tak, aby odpovídaly názvům serveru, databáze, elastického fondu nebo spravované instance SQL.
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;
Použití T-SQL k zobrazení vlastností databáze, elastického fondu nebo spravované instance SQL
V tomto příkladu dotaz vrátí sadu všech databází, elastických fondů nebo instancí spravovaných SQL, ze kterých se během posledních 24 hodin shromáždila aspoň jedna ukázka v odpovídající datové sadě Vlastností. Jinými slovy, každý řádek představuje cíl monitorování s jeho naposledy pozorovanými vlastnostmi.
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;
Zobrazení statistik modulu runtime dotazu pomocí jazyka T-SQL
Tento dotaz vrátí dotazy s nejvyšším využitím prostředků napříč vašimi aktivy Azure SQL. Změňte proměnnou @TopQueriesBy
tak, aby našel nejčastější dotazy podle libovolné metriky úložiště dotazů, včetně času procesoru, uplynulého času, počtu provádění atd. Můžete také nastavit proměnné pro filtrování podle časového intervalu, typu spuštění dotazu a hodnoty hash dotazu konkrétního dotazu nebo zaměřit se na databáze z konkrétního logického serveru, elastického fondu nebo spravované instance SQL.
Dotaz používá datovou sadu statistik modulu runtime dotazu k vrácení zadaných nejčastějších dotazů. Vrátí také jejich pořadí podle metriky spotřeby všech ostatních prostředků.
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;
Použití T-SQL k analýze čítačů výkonu v průběhu času
V tomto příkladu dotaz vrátí hodnoty čítače výkonu za posledních 30 minut.
Tento příklad používá kumulativní čítače výkonu, například Total request count
a Query optimizations/sec
. Kumulativní znamená, že hodnota čítače se neustále zvyšuje, když dojde k aktivitě dotazu. Dotaz používá analytickou funkci LAG() k výpočtu rozdílu nebo rozdílu mezi hodnotou čítače v každém vzorku a její hodnotou v předchozím vzorku k získání počtu požadavků a optimalizací, ke kterým došlo od předchozího vzorku.
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;
Analýza čítačů výkonu k určitému bodu v čase pomocí T-SQL
Dalším příkladem jsou čítače výkonu k určitému bodu v čase, které hlásí naposledy pozorovanou hodnotu, například Active memory grants count
, Pending memory grants count
a 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;
Použití T-SQL k analýze kumulativních čekání v průběhu času
V tomto příkladu dotaz vrátí prvních 10 typů čekání podle průměrné kumulativní doby čekání v intervalu 30 minut. Kumulativní znamená, že dotaz vypočítá celkový čas v milisekundách, který strávil čekáním v každém typu čekání všemi požadavky za každou sekundu. Vzhledem k tomu, že se může souběžně spouštět více požadavků (a čekat), může kumulativní doba čekání v každé sekundě být více než jedna sekunda.
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;
Související obsah
- Monitorování úloh Azure SQL pomocí sledovacího procesu databáze (Preview)
- Rychlý start: Vytvoření sledovacího procesu databáze pro monitorování Azure SQL (Preview)
- Vytvoření a konfigurace sledovacího procesu databáze (Preview)
- Nejčastější dotazy ke sledovacím procesům databáze
- dotazovací jazyk Kusto výukových materiálů