Share via


Veritabanı izleyicisi izleme verilerini analiz etme (önizleme)

Şunlar için geçerlidir:Azure SQL Veritabanı Azure SQL Yönetilen Örneği

Azure portalında panoları kullanmanın yanı sıra, Microsoft Fabric'te Power BI, Grafana, Azure Veri Gezgini veya Gerçek Zamanlı Analiz'de SQL izleme verilerini görüntülemek ve analiz etmek için görselleştirmeler oluşturmanın yanı sıra, izleme veri deponuzu doğrudan sorgulayabilirsiniz.

Bu makale, toplanan izleme verilerini çözümlemeye başlamanıza yardımcı olan KQL ve T-SQL sorgularının örneklerini içerir.

İzleme verilerini analiz etmek için KQL kullanma

Toplanan izleme verilerini analiz etmek için önerilen yöntem Kusto Sorgu Dili (KQL) kullanmaktır. KQL telemetriyi, ölçümleri ve günlükleri sorgulamak için idealdir. Metin arama ve ayrıştırma, zaman serisi işleçleri ve işlevleri, analiz ve toplama ve veri analizini kolaylaştıran diğer birçok dil yapısı için kapsamlı destek sağlar.

KQL kavramsal olarak SQL'e benzer. Tablolar ve sütunlar gibi şema varlıkları üzerinde çalışır ve SQL'deki , WHEREJOIN, ve yan tümcelerine SELECTkarşılık gelen proje, kısıtlama, birleştirme ve GROUP BY özetleme gibi ilişkisel işlemleri destekler.

KQL sorguları yazmak ve yürütmek için Kusto Gezgini'ni veya Azure Veri Gezgini web kullanıcı arabirimini kullanabilirsiniz. Kusto Gezgini tam özellikli bir Windows masaüstü yazılımıdır, Azure Veri Gezgini web kullanıcı arabirimi ise KQL sorguları yürütmenize ve sonuçları herhangi bir platformda tarayıcıda görselleştirmenize olanak tanır.

Microsoft Fabric'te Gerçek Zamanlı Analiz'de bir veritabanını sorgulamak için de bu araçları kullanabilirsiniz. Bağlanmak için Gerçek Zamanlı Analiz veritabanınızın Sorgu URI'sini kullanarak yeni bir bağlantı ekleyin. Ayrıca, Gerçek Zamanlı Analiz kullanıyorsanız, KQL sorgu kümelerini kullanarak izleme verilerini analiz edebilirsiniz. KQL sorgu kümesi paylaşılabilir yapıt olarak kaydedilebilir ve Power BI raporları oluşturmak için kullanılabilir.

KQL'yi kullanmaya yeni başladıysanız, aşağıdaki kaynaklar kullanmaya başlamanıza yardımcı olabilir:

Aşağıdaki örnekler, toplanan SQL izleme verilerini görüntülemek ve analiz etmek için kendi KQL sorgularınızı yazmanıza yardımcı olabilir. Bu örnekleri kendi veri görselleştirmelerinizi ve panolarınızı oluştururken başlangıç noktası olarak da kullanabilirsiniz.

Zaman içinde kaynak tüketimini sorgulamak için KQL kullanma

Bu örnekte sorgu, son bir saat içinde veritabanının, elastik havuzun veya SQL yönetilen örneğinin birincil çoğaltması için kaynak tüketimi ölçümlerini (CPU, çalışanlar, günlük yazma aktarım hızı vb.) döndürür. Sonuç kümesini döndürmeye ek olarak, bunu bir zaman grafiği olarak görselleştirir.

Bu ve diğer örneklerde let deyimlerindeki değişkenleri sunucunuzun, veritabanınızın, elastik havuzunuzun veya SQL yönetilen örneğinizin adlarıyla eşleşecek şekilde değiştirin. Farklı bir zaman aralığı kullanmak için değişkenini duration değiştirin. Daha fazla bilgi için bkz . zaman aralığı değişmez değerleri.

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;

Veritabanı, elastik havuz veya SQL yönetilen örneği özelliklerini görüntülemek için KQL kullanma

Bu örnekte sorgu, son bir gün içinde ilgili Özelliklerveri kümesindeki en az bir örneğin toplandığı tüm veritabanlarını, elastik havuzları veya SQL yönetilen örneklerini döndürür. Başka bir deyişle, her satır en son gözlemlenen özellikleriyle bir izleme hedefini temsil eder.

arg_max() işlevi, hedefi tanımlayan belirtilen sütun kümesinin en son satırını döndürmek için verileri toplar. Örneğin, Azure SQL veritabanları için bu küme , , database_namereplica_typeşeklindedirlogical_server_name.

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;

Çalışma zamanı istatistiklerini sorgulamak için KQL kullanma

Bu sorgu, Azure SQL varlığınızda en çok kaynak tüketen sorguları döndürür. Cpu süresi, geçen süre, yürütme sayısı vb. dahil olmak üzere sorguları Sorgu Deposu ölçümlerine göre sıralamak için bir değişkeni değiştirin. Değişkenleri bir zaman aralığına, sorgu yürütme türüne ve sorgu metnine göre filtrelemek için de ayarlayabilirsiniz. Belirli bir mantıksal sunucuya, elastik havuza, SQL yönetilen örneğine veya veritabanına odaklanmak için değişkenleri ayarlayın.

Sorgu, belirttiğiniz en çok sorgu sayısını döndürmek için Sorgu çalışma zamanı istatistikleriveri kümesini kullanır ve diğer tüm kaynak tüketimi ölçümlerine göre derecelendirmelerini içerir.

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;

Zaman içindeki performans sayaçlarını analiz etmek için KQL kullanma

Bu örnekte sorgu, belirtilen bitiş saatinden 30 dakika önce başlayan bir zaman aralığı için performans sayacı değerlerini döndürür.

Bu örnekte ve Query optimizations/secgibi Total request count birikmeli performans sayaçları kullanılır. Kümülatif, SQL sorgu etkinliği gerçekleştikçe sayaç değerinin artmaya devam ettiğini gösterir. Bu örnekteki sorgu, önceki örnekten bu yana gerçekleşen istek ve iyileştirme sayısını elde etmek için her örnekteki sayaç değeri ile önceki örnekteki değeri arasındaki farkı veya deltayı hesaplar ve sonra bu ölçümleri bir zaman grafiğinde görselleştirir.

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;

Aşağıdaki örnek, , Pending memory grants countve Processes blockedgibi Active memory grants counten son gözlemlenen değeri raporlayan belirli bir noktaya performans sayaçları içindir. Zaman aralığı son 30 dakikadır.

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;

Aşağıdaki örnek, Azure SQL Veritabanı kullanıcı ve iç kaynak havuzları ile iş yükü grupları için CPU kullanımını grafiklendirmek için Performans sayaçlarını (ayrıntılı) veri kümesini kullanır. Daha fazla bilgi için bkz . Kullanıcı iş yüklerine ve iç işlemlere göre kaynak tüketimi.

Kullanıcı iş yükleri veya UserPool kaynak havuzlarında SloSharedPool1 çalışırken, diğer tüm kaynak havuzları çeşitli sistem iş yükleri için kullanılır.

Benzer şekilde, kullanıcı iş yükleri ile UserPrimaryGroup.DBIdbaşlayan adlı iş yükü gruplarında çalışırken, diğer tüm iş yükü grupları çeşitli sistem iş yükleri için kullanılır. Örneğin, veritabanı izleyicisi izleme sorguları iş yükü grubunda çalışıyor 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;

Zaman içindeki kümülatif beklemeleri analiz etmek için KQL kullanma

Bu örnekte, bir zaman aralığında en iyi SQL bekleme türlerinin nasıl grafikleneceği gösterilmektedir. Sorgu, geçen sürenin saniye başına milisaniye cinsinden her bir bekleme türü için birikmeli bekleme süresini hesaplar. Sorgu değişkenlerini, aralık başlangıç ve bitiş saatini, eklenecek en fazla bekleme türlerinin sayısını ve grafikteki veri noktaları arasındaki adımı ayarlamak için ayarlayabilirsiniz.

Sorgu, performansı geliştirmek için iki teknik kullanır:

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;

İzleme verilerini analiz etmek için T-SQL kullanma

T-SQL'i zaten biliyorsanız, KQL öğrenmek zorunda kalmadan SQL izleme verilerini sorgulamaya ve analiz etmeye hemen başlayabilirsiniz. Ancak KQL, telemetri verilerini sorgulamak için benzersiz destek sağladığından Azure Veri Gezgini veya Gerçek Zamanlı Analiz'de verileri sorgulamak için önerilen dildir.

SQL Server Management Studio (SSMS), Azure Data Studio ve diğer yaygın araçlardan Azure Veri Gezgini veya Gerçek Zamanlı Analiz veritabanınıza bağlanabilirsiniz. Azure Veri Gezgini veya KQL veritabanını SQL Server veya Azure SQL veritabanıymış gibi sorgulayabilirsiniz. Daha fazla bilgi için bkz. SQL Server öykünmesini kullanarak azure Veri Gezgini verileri sorgulama.

Not

Azure Veri Gezgini ve Gerçek Zamanlı Analiz'de her T-SQL yapısı desteklenmez. Ayrıntılar için bkz . T-SQL kullanarak verileri sorgulama.

T-SQL desteğinin gereksinimleriniz için yetersiz olduğunu fark ederseniz veya T-SQL sorgularınızı KQL'ye dönüştürerek gelişmiş analiz özelliklerini kullanmak istiyorsanız, sql-Kusto Sorgu Dili bilgi sayfası T-SQL sorgularınızı KQL'ye çevirmenize yardımcı olabilir.

Aşağıdaki örneklerde, T-SQL kullanarak veritabanı izleyicisi veri deposundaki izleme verilerini sorgulama gösterilmektedir.

Zaman içindeki kaynak tüketimini analiz etmek için T-SQL kullanma

Bu örnekte sorgu, son bir saat içinde veritabanının, elastik havuzun veya SQL yönetilen örneğinin birincil çoğaltması için kaynak tüketimi ölçümlerini (CPU, çalışanlar, günlük yazma aktarım hızı vb.) döndürür.

Bu ve diğer örneklerde, deyimindeki DECLARE değişkenleri sunucunuzun, veritabanınızın, elastik havuzunuzun veya SQL yönetilen örneğinizin adlarıyla eşleşecek şekilde değiştirin.

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;

Veritabanı, elastik havuz veya SQL yönetilen örneği özelliklerini görüntülemek için T-SQL kullanma

Bu örnekte sorgu, son 24 saat içinde ilgili Özelliklerveri kümesindeki en az bir örneğin toplandığı tüm veritabanlarını, elastik havuzları veya SQL yönetilen örneklerini döndürür. Başka bir deyişle, her satır en son gözlemlenen özellikleriyle bir izleme hedefini temsil eder.

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;

Çalışma zamanı istatistiklerini sorgulamak için T-SQL kullanma

Bu sorgu, Azure SQL varlığınız genelinde en çok kaynak tüketen sorguları döndürür. DEĞIŞKENini @TopQueriesBy , CPU süresi, geçen süre, yürütme sayısı vb. dahil olmak üzere herhangi bir Sorgu Deposu ölçümüne göre en çok kullanılan sorguları bulmak için değiştirin. Değişkenleri belirli bir sorgunun zaman aralığına, sorgu yürütme türüne ve sorgu karmasına göre filtrelemek veya belirli bir mantıksal sunucudan, elastik havuzdan veya SQL yönetilen örneğinden veritabanlarına odaklanmak için de ayarlayabilirsiniz.

Sorgu, belirttiğiniz en önemli sorguları döndürmek için Sorgu çalışma zamanı istatistikleriveri kümesini kullanır. Ayrıca diğer tüm kaynak tüketimi ölçümlerine göre derecelerini döndürür.

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;

Zaman içindeki performans sayaçlarını analiz etmek için T-SQL kullanma

Bu örnekte sorgu, son 30 dakika için performans sayacı değerlerini döndürür.

Bu örnekte ve Query optimizations/secgibi Total request count birikmeli performans sayaçları kullanılır. Kümülatif, sorgu etkinliği gerçekleştikçe sayaç değerinin artmaya devam ettiğini gösterir. Sorgu, önceki örnekten bu yana gerçekleşen istek ve iyileştirme sayısını elde etmek üzere her örnekteki sayaç değeri ile önceki örnekteki değeri arasındaki farkı veya deltayı hesaplamak için LAG() analiz işlevini kullanır.

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;

Belirli bir noktaya performans sayaçlarını analiz etmek için T-SQL kullanma

Sonraki örnek, , Pending memory grants countve Processes blockedgibi Active memory grants counten son gözlemlenen değeri raporlayan belirli bir noktaya performans sayaçlarıdır.

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;

Zaman içindeki kümülatif beklemeleri analiz etmek için T-SQL kullanma

Bu örnekte sorgu, 30 dakikalık bir aralık boyunca ortalama birikmeli bekleme süresine göre ilk 10 bekleme türünü döndürür. Kümülatif, sorgunun her saniyedeki tüm isteklere göre her bir bekleme türü altında beklemeye harcanan toplam süreyi milisaniye cinsinden hesapladığı anlamına gelir. Birden çok istek eşzamanlı olarak yürütülebildiğinden (ve bekleyebildiğinden), her saniyedeki birikmeli bekleme süresi bir saniyeden fazla olabilir.

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;