05.8 SQL Query History, Monitoring & Cost Optimization
A production SQL platform needs more than fast queries. You need to know who is running what, how long it takes, what it costs, where capacity is being consumed, and whether performance is getting worse.
1. Learning objectives
By the end of this topic you should be able to:
- Use the Query History UI and
system.query.history. - Build operational metrics for duration, failures, queue time, I/O, and throughput.
- Attribute workload usage with query and compute tags.
- Correlate queries, warehouse events, and billing usage.
- Understand DBUs, SKU-based billing records, and list-price estimates.
- Build team, project, application, and environment cost views.
- Diagnose performance regressions and capacity problems.
- Design cost guardrails without damaging developer productivity.
- Build an enterprise SQL observability operating model.
2. The enterprise monitoring model
SQL workload
↓
Query History
↓
Performance metrics ──→ Query Profile
↓
Workload attribution ──→ Tags
↓
Warehouse events
↓
Billing usage
↓
Dashboards / alerts / budgets
↓
Optimization decisions
Databricks currently provides system.query.history for query records, system.compute.warehouse_events for warehouse lifecycle/scaling events, system.compute.warehouses for warehouse configuration history, and system.billing.usage for billable usage. citeturn304353search1turn304353search5
3. Query History UI
The Query History page lets you filter previous runs by user, date range, compute, duration, status, statement type, statement ID, and query tags. Query details include the statement, duration, rows returned, I/O metrics, and access to Query Profile. citeturn304353search3
Use it for the first response to a production incident:
Is it slow?
↓
Which query?
↓
Which user/application?
↓
Which warehouse?
↓
How long?
↓
Where is time spent?
↓
How much data moved?
Important metrics
- Wall-clock duration
- Execution duration
- Queue/capacity waiting
- Rows read
- Rows returned
- Input/output volume
- Query status
- Query source
- Query tags
4. system.query.history
The query history system table is the foundation for SQL workload observability. It contains records for SQL warehouses and supported serverless compute workloads. Records are typically available within about one hour, and the table retains 365 days of regional history. citeturn304353search5turn304353search4
Example: recent slow queries
SELECT
statement_id,
workspace_id,
executed_by,
warehouse_id,
execution_status,
total_duration_ms,
execution_duration_ms,
waiting_at_capacity_duration_ms,
read_rows,
produced_rows,
statement_text
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 1 DAY
ORDER BY total_duration_ms DESC
LIMIT 50;
Production interpretation
A 15-minute query is not necessarily a 15-minute compute problem.
Total duration
├── queue / capacity wait
├── planning / optimization
├── execution
└── other scheduling overhead
Use the breakdown to identify the actual bottleneck.
5. Failed query monitoring
SELECT
execution_status,
COUNT(*) AS query_count
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 7 DAY
GROUP BY execution_status
ORDER BY query_count DESC;
Failure rate is more useful when segmented by workload:
SELECT
executed_by,
COUNT(*) AS total_queries,
SUM(CASE WHEN execution_status = 'FAILED' THEN 1 ELSE 0 END) AS failures
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 7 DAY
GROUP BY executed_by
ORDER BY failures DESC;
For an enterprise platform, trend failure rate rather than reacting only to individual incidents.
6. Slow-query SLOs
Define operational targets such as:
| Metric | Example SLO |
|---|---|
| Dashboard p95 | < 10 sec |
| Critical report p95 | < 60 sec |
| ETL query success | > 99% |
| Capacity waiting | < 5% of runtime |
| Failed production queries | < 1% |
The numbers are examples, not universal Databricks limits. Set targets from business requirements and workload characteristics.
7. Query tags — the bridge to FinOps
Query tags are custom key-value pairs that can group SQL workloads by business context and track costs. Tags appear in system.query.history and the Query History UI. citeturn304353search0
Example taxonomy:
domain:finance
team:analytics
project:sales360
environment:prod
application:powerbi
cost_center:FIN-042
Design rules
- Use stable controlled values.
- Do not put secrets or sensitive data in tags.
- Keep values short and searchable.
- Define ownership for the taxonomy.
- Make tags part of the platform operating model.
8. Cost attribution
A useful enterprise chain is:
Business unit
↓
Project / application
↓
Query tags
↓
Query history
↓
Warehouse / serverless usage
↓
system.billing.usage
↓
Chargeback / showback
Databricks recommends tags for attributing usage to teams, projects, workspaces, or users. citeturn304353search11turn304353search17
Showback vs chargeback
Showback: report consumption without directly billing the team.
Chargeback: assign actual internal cost responsibility.
Start with showback when cost data quality is immature. Move to chargeback once tagging and ownership are reliable.
9. system.billing.usage
The billable usage system table contains account-level billing records, including usage metadata, identity metadata, and custom tags. It is the source of truth for actual billable usage. citeturn304353search12turn304353search2
Example: DBUs by day and SKU:
SELECT
usage_date,
sku_name,
ROUND(SUM(usage_quantity), 2) AS total_dbus
FROM system.billing.usage
WHERE usage_date >= CURRENT_DATE() - 30
GROUP BY usage_date, sku_name
ORDER BY usage_date DESC, total_dbus DESC;
Do not treat DBUs as dollars by themselves. Price depends on SKU, contract, discounts, cloud infrastructure, and pricing terms.
10. Estimating list-price cost
Databricks provides system.billing.list_prices so usage can be joined to historical pricing. citeturn304353search1
Conceptually:
SELECT
u.usage_date,
u.sku_name,
SUM(u.usage_quantity) AS dbus,
SUM(u.usage_quantity * p.pricing.default) AS estimated_list_cost
FROM system.billing.usage u
LEFT JOIN system.billing.list_prices p
ON u.sku_name = p.sku_name
AND u.usage_start_time >= p.price_start_time
AND u.usage_start_time < COALESCE(p.price_end_time, NOW())
WHERE u.usage_date >= CURRENT_DATE() - 30
GROUP BY u.usage_date, u.sku_name;
This is a list-price estimate, not necessarily the final invoice amount.
11. Warehouse events
system.compute.warehouse_events captures events such as warehouse start, stop, scale-up, and scale-down. citeturn304353search1
This is valuable because cost is a time-series behavior, not just a monthly number.
Queries arrive
↓
Warehouse scales up
↓
Concurrency improves
↓
Workload falls
↓
Warehouse scales down
↓
Idle cost avoided
Correlate scaling behavior with query volume before changing warehouse configuration.
12. Warehouse configuration history
system.compute.warehouses contains configuration snapshots over time. citeturn304353search1
This allows you to investigate questions such as:
- When was the warehouse resized?
- Did performance change after the change?
- Did auto-stop settings change?
- Was scaling configuration altered?
- Did a team increase capacity without reducing query cost?
This is essential for performance regression analysis.
13. Query cost is not only query duration
Consider two queries:
| Query | Runtime | Resource behavior |
|---|---|---|
| A | 30 sec | efficient, small scan |
| B | 30 sec | huge scan, high concurrency |
Same runtime does not imply same cost or platform impact.
Therefore optimize for a multidimensional objective:
Latency + throughput + reliability + resource consumption + business value
14. Cost optimization framework
Use five levers:
Lever 1 — Read less
- Reduce scanned data.
- Select required columns.
- Improve pruning and table layout.
Lever 2 — Compute less
- Remove unnecessary transformations.
- Pre-aggregate where justified.
- Avoid repeated expensive computation.
Lever 3 — Run efficiently
- Choose appropriate warehouse/compute.
- Use autoscaling appropriately.
- Avoid unnecessary always-on capacity.
Lever 4 — Attribute
- Tag workloads.
- Assign owners.
- Build showback dashboards.
Lever 5 — Govern
- Budgets.
- Alerts.
- Policies.
- Review cycles.
15. Serverless and warehouse selection
Current Databricks guidance generally recommends serverless compute for many workloads because of faster startup, automatic scaling, and lower management overhead; serverless SQL warehouses are recommended for BI, ETL, and exploratory SQL workloads where available. citeturn304353search6
But architecture is not simply “serverless is always cheaper.” Evaluate:
- workload shape
- concurrency
- startup sensitivity
- network requirements
- supported features
- data access model
- actual measured cost
For example, Pro SQL warehouses can be appropriate when custom networking is required. citeturn304353search6
16. Capacity waiting vs execution time
Suppose:
Query A
Execution: 20 sec
Capacity wait: 2 sec
Total: 22 sec
Query B
Execution: 20 sec
Capacity wait: 90 sec
Total: 110 sec
Rewriting Query B may not solve the primary problem. The platform has a capacity/concurrency issue.
Architect decision:
High execution time → tune query
High capacity wait → tune concurrency/capacity
Both high → address both
17. Cost anomaly detection
A simple daily trend can expose unusual consumption:
SELECT
usage_date,
SUM(usage_quantity) AS dbus
FROM system.billing.usage
WHERE usage_date >= CURRENT_DATE() - 60
GROUP BY usage_date
ORDER BY usage_date;
Then compare recent consumption against a baseline.
Example anomaly signals:
- DBUs suddenly double.
- One project consumes most incremental spend.
- A new warehouse stays active overnight.
- Query volume is stable but cost rises.
- A release increases bytes scanned per query.
18. Cost per query and cost per business outcome
Raw DBUs are useful, but business metrics are better.
Cost / dashboard refresh
Cost / million rows processed
Cost / ETL run
Cost / successful pipeline
Cost / 1,000 customer insights
This changes the discussion from infrastructure spend to business efficiency.
19. Enterprise SQL observability dashboard
Build a dashboard with five pages:
Page 1 — Executive
- Daily/monthly spend
- DBU trend
- Top cost centers
- Budget variance
Page 2 — Workload
- Query count
- p50/p95/p99 duration
- failure rate
- top queries
Page 3 — Warehouse
- utilization
- queue time
- scaling events
- configuration changes
Page 4 — Cost attribution
- team
- project
- application
- environment
- workspace
Page 5 — Optimization
- highest scan volume
- highest shuffle/resource consumption
- repeated slow queries
- regression candidates
20. Alert design
Avoid alerting on every slow query.
Better alerts:
- Critical workload failure rate crosses threshold.
- p95 latency increases materially for a key dashboard.
- Capacity waiting exceeds target.
- Daily spend exceeds budget trajectory.
- A new workload produces an abnormal scan volume.
- A warehouse remains active outside expected operating hours.
An alert should answer three questions:
What happened?
Why should I care?
Who owns it?
21. Budgets and guardrails
Databricks budgets can monitor spend and enforce usage thresholds in supported scenarios. Budget estimates can differ temporarily from system.billing.usage; Databricks identifies the billing system table as the source of truth for actual billable usage. citeturn304353search16
Use layered controls:
Budget
↓
Alert
↓
Owner notification
↓
Investigation
↓
Policy / workload correction
Do not make hard blocking the first response to every anomaly. Protect critical workloads while controlling discretionary consumption.
22. Query monitoring SQL toolkit
Top slow queries
SELECT
statement_id, executed_by, total_duration_ms,
execution_duration_ms, statement_text
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 7 DAY
ORDER BY total_duration_ms DESC
LIMIT 100;
Top users by query count
SELECT executed_by, COUNT(*) AS queries
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 30 DAY
GROUP BY executed_by
ORDER BY queries DESC;
Capacity waiting
SELECT
statement_id,
total_duration_ms,
waiting_at_capacity_duration_ms
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 7 DAY
AND waiting_at_capacity_duration_ms > 0
ORDER BY waiting_at_capacity_duration_ms DESC;
Tagged workload
SELECT
query_tags,
COUNT(*) AS queries,
AVG(total_duration_ms) AS avg_duration_ms
FROM system.query.history
WHERE start_time >= NOW() - INTERVAL 30 DAY
GROUP BY query_tags
ORDER BY queries DESC;
Always validate column names against the current system-table schema in your environment before productionizing monitoring SQL.
23. Hands-on labs
Lab A — Build a slow-query report
Use system.query.history to produce top 50 queries by duration and group them by owner.
Lab B — Failure SLO
Calculate daily failed-query percentage and identify regression days.
Lab C — Capacity diagnosis
Compare execution duration with capacity-wait duration and classify bottlenecks.
Lab D — Cost attribution
Create a tag taxonomy and build a team/project cost report.
Lab E — Warehouse scaling
Join warehouse events with query activity and identify idle or over-provisioned periods.
Lab F — Cost anomaly
Create a 60-day DBU trend and flag days with abnormal consumption.
Lab G — Executive dashboard
Build the five-page SQL observability dashboard described above.
24. Enterprise operating model
A mature organization defines roles:
| Role | Responsibility |
|---|---|
| Data engineer | Query/pipeline efficiency |
| Analytics engineer | SQL/model quality |
| Platform engineer | Warehouse reliability |
| FinOps | Cost attribution and budgets |
| Architect | Platform standards and trade-offs |
| Product owner | Business SLOs |
This avoids the anti-pattern where everyone sees cost but nobody owns it.
25. Architect reference architecture
┌────────────────────┐
│ BI / Apps / Jobs │
└─────────┬──────────┘
↓
┌────────────────────┐
│ SQL Warehouses │
└─────────┬──────────┘
↓
┌───────────┴───────────┐
↓ ↓
system.query.history warehouse events
│ │
└───────────┬───────────┘
↓
┌────────────────────┐
│ Observability model│
└─────────┬──────────┘
↓
┌───────────────┼───────────────┐
↓ ↓ ↓
Cost Performance SLOs
│ │ │
└───────────────┼───────────────┘
↓
Governance / FinOps
Billing usage is then joined to ownership dimensions to build enterprise chargeback/showback.
26. Common mistakes
Mistake 1 — Looking only at monthly spend
You need workload-level attribution to find causes.
Mistake 2 — Treating DBUs as invoice dollars
Use pricing and contract context.
Mistake 3 — No tagging strategy
Unattributed spend becomes difficult to govern.
Mistake 4 — Alerting on every query
Alert fatigue destroys operational value.
Mistake 5 — Optimizing only latency
A fast but extremely expensive query can still be a poor design.
Mistake 6 — Ignoring data latency
System tables are operational data products; understand their availability windows.
27. Interview questions
Foundation
- What is
system.query.history? - What is
system.billing.usage? - What is the difference between query duration and capacity wait?
- Why are query tags useful?
Troubleshooting
- How would you find the top 10 expensive workloads?
- How would you identify a warehouse capacity bottleneck?
- How would you detect a performance regression?
- How would you investigate a sudden DBU spike?
Architect
- How would you design chargeback across 50 business units?
- How would you design SQL observability for 100+ warehouses?
- How would you balance cost optimization with dashboard SLOs?
- When would you prefer serverless versus Pro/classic warehouse?
- What governance controls would you implement without slowing developers?
28. Production checklist
- Query History is actively used for incident investigation.
-
system.query.historyis available to the monitoring team. - Query/compute tags follow a controlled taxonomy.
- Billing usage is integrated into cost reporting.
- Warehouse events are monitored.
- Query latency SLOs exist for critical workloads.
- Failure-rate monitoring exists.
- Capacity waiting is monitored.
- Cost anomalies are detected.
- Owners exist for major workloads.
- Budget/alert controls are defined.
- Performance and cost are reviewed together.
29. Key takeaway
Enterprise SQL optimization ends when you can measure, attribute, explain, and govern the workload — not merely when one query becomes faster.
The architect mental model is: Observe → Attribute → Diagnose → Optimize → Govern → Repeat.
Next: 06. Delta Lake.