Find Your Slowest SQL Queries With Azure Log Analytics (KQL Recipes)

When a .NET application running on Azure feels slow, the database is the usual suspect — but “the database is slow” is a hunch, not a diagnosis. If your app sends telemetry to Application Insights, every SQL call is already being recorded as a dependency, and a handful of KQL queries in Log Analytics will tell you exactly which statements are hurting you, when, and how badly. Here are the queries we run first.

Where the data lives

Application Insights records each outbound SQL call in the dependencies table, with type == "SQL", the statement in data, the target database in target, the duration in milliseconds, and a success flag. Everything below queries that table. (On a workspace-based resource the same data is in the AppDependencies table — the shape is identical.)

1. The slowest individual calls

Start with the worst single offenders — the calls that blew past a threshold. This surfaces the pathological one-off queries:

dependencies
| where timestamp > ago(24h)
| where type == "SQL"
| where duration > 1000            // slower than 1 second
| project timestamp, target, data, duration, success
| order by duration desc
| take 50

2. The biggest offenders by total time

The most important query on this page. A statement that takes 200 ms but runs fifty thousand times a day costs you far more than a 5-second query that runs twice. Rank by total accumulated time, and bring the percentiles along so you see the typical case and the tail together:

dependencies
| where timestamp > ago(24h)
| where type == "SQL"
| summarize
    calls        = count(),
    totalMs      = sum(duration),
    avgMs        = avg(duration),
    p95Ms        = percentile(duration, 95),
    p99Ms        = percentile(duration, 99)
  by data
| order by totalMs desc
| take 25

The totalMs column is where you should spend your optimisation effort. Fixing the top few rows here is what actually moves the needle.

3. Per-day trend

Is it getting worse over time? Bucket by day to see the trend as data volume grows:

dependencies
| where timestamp > ago(30d)
| where type == "SQL"
| summarize avgMs = avg(duration), p95Ms = percentile(duration,95), calls = count()
    by bin(timestamp, 1d)
| order by timestamp asc
| render timechart

4. Per-hour trend

The same view at hourly resolution shows how load and latency move through a single day:

dependencies
| where timestamp > ago(3d)
| where type == "SQL"
| summarize avgMs = avg(duration), calls = count()
    by bin(timestamp, 1h)
| order by timestamp asc
| render timechart

5. Finding the peak hour

To answer “when are we busiest, and does latency suffer then?”, collapse across days by hour-of-day. This tells you the peak window and whether your database degrades under it:

dependencies
| where timestamp > ago(14d)
| where type == "SQL"
| extend hour = hourofday(timestamp)
| summarize calls = count(), avgMs = avg(duration), p95Ms = percentile(duration,95)
    by hour
| order by calls desc

Sort by calls to find your peak load hour; glance across to p95Ms to see whether latency climbs when traffic does. A query that is fine at midnight but slow at your busiest hour is a capacity or locking problem, not a bad query — and that distinction changes the fix.

6. Failing and timing-out calls

Slowness and failure often share a root cause, so it is worth pulling the unsuccessful calls too:

dependencies
| where timestamp > ago(24h)
| where type == "SQL" and success == false
| summarize failures = count() by data, target
| order by failures desc

How to read the results together

  • High total time, low average → a frequently-called query; optimise it or call it less (caching, batching).
  • High average, high p99 → a genuinely expensive statement; look at its execution plan and indexing.
  • Fine off-peak, slow at peak → contention or capacity, not the query itself.
  • Rising day-over-day → a query that does not scale with your data growth.

Takeaway

You do not need guesswork to find slow SQL on Azure — the telemetry is already there, and a few KQL queries turn it into a ranked, evidence-backed list of exactly what to fix. Rank by total time, watch the per-hour and peak views, and let the data point you at the handful of statements that actually matter. We do this kind of performance investigation on Azure-hosted .NET systems regularly; reach out if your app is slow and you want to know precisely why.