Introduction
Predicting SQL query performance before execution helps teams prevent slow queries from degrading application performance, reduce costly database incidents, and guide developers to write efficient SQL. A Workload Analyzer uses historical telemetry and machine learning to estimate execution time, CPU cost, I/O, and likelihood of timeouts or plan regressions for a given SQL query and its parameters.
This article explains how to design and implement a production-ready Workload Analyzer using:
Telemetry collection from SQL Server / Postgres (execution stats, plans, waits)
Feature engineering over text, plans, and statistics
ML model choices and training pipelines (.NET-friendly)
Runtime integration with application stack (ASP.NET Core + Angular) to warn or auto-throttle risky queries
Operational concerns, testing, and metrics
Headers are compact and written in clear technical prose suitable for senior developers.
Goals and scope
Primary goals
Predict query latency (ms) and resource cost (CPU, logical I/O) for a SQL text + parameters and a target database state.
Predict probability of timeout or plan regression.
Provide explainable feedback (hotspots: missing index, expensive join, large scan).
Integrate into CI and runtime: pre-deploy checks and runtime safety gates.
Non-goals
Replace the query optimizer — the analyzer augments DBA insight.
Exact millisecond accuracy under all dynamic loads — provide probabilistic estimates and uncertainty.
High-level architecture
┌─────────────────────┐
│ Application / CI │
│ (ASP.NET Core / CI) │
└─────────┬───────────┘
│ SQL text + params
▼
┌─────────────────────┐
│ Workload Analyzer │
│ (API + Model Server)│
└──────┬─────┬────────┘
│ │
┌───────────────▼─┐ ┌─▼────────────────┐
│ Feature Store │ │ Model Training │
│ (time-series DB)│ │ Pipeline (ML Ops) │
└────────┬────────┘ └────────┬─────────┘
│ │
┌────────▼────────┐ ┌───────▼─────────┐
│ Telemetry Source│ │ Explainability │
│ (DB DMVs, APM) │ │ & Suggestions │
└─────────────────┘ └─────────────────┘
Components
Telemetry Collector: gathers historical execution stats and plans.
Feature Store: stores precomputed features per query fingerprint and time-windowed metrics.
Model Training Pipeline: offline training, validation, and periodic retraining.
Prediction API: .NET service that scores incoming queries.
UI: Angular dashboard showing predictions, confidence, and remediation suggestions.
Telemetry collection
Collect rich historical signals to train accurate models:
Execution metrics
Duration (ms), CPU time (ms), logical and physical reads, writes, rows returned, plan id, compile time.
Query fingerprint
Normalize SQL (remove literals) and compute fingerprint (hash). Useful for grouping.
Query text and plan
Store normalized text, query plan XML/JSON (operator tree), index usage.
Runtime context
Parameter values (hashed or binned), session settings, transaction isolation, connection pool state.
Server state and load
CPU load, memory pressure, concurrent active sessions, buffer cache hit ratio, recent blocking/waits.
Schema metadata
Table row counts, index cardinalities, column stats (histograms), last statistics update time.
Temporal context
Time of day, day of week, maintenance windows, backup jobs may affect performance.
Sources
SQL Server: Query Store / DMVs (
sys.query_store_*,sys.dm_exec_query_stats,sys.dm_exec_query_plan)Postgres:
pg_stat_statements,pg_stat_activity,EXPLAIN (ANALYZE, BUFFERS)outputAPM: Application-level traces and logs (OpenTelemetry)
OS metrics: CPU, memory, disk I/O
Collect telemetry in a time-series store (Prometheus, InfluxDB) or a feature store (Feast, custom DB) for model training.
Feature engineering
Good features matter more than fancy models. Features fall into categories:
Query text features
Token counts, number of JOINs, number of tables referenced
Presence of
ORDER BY,GROUP BY, window functions, aggregatesSubquery count, correlated subquery flag
Estimated cardinalities parsed from plans (rows estimated vs actual)
Text embeddings of normalized SQL (use Sentence-BERT or TF-IDF)
Plan-based features
Plan shape features: depth, number of operators, most expensive operator type (Hash Join, Nested Loop, Seq Scan)
Operator costs as reported by optimizer
Index seek vs scan flags per table
Parallelism (degree of parallelism used)
Schema / stats features
Table row counts (log scale)
Index fragmentation, index covered columns count
Column histogram skewness
Parameter features
Parameter cardinality buckets (low/medium/high distinct values)
Literal size (text length)
Server-load features
Current CPU utilization, I/O queue length, buffer cache hit rate
Concurrent sessions, blocking count
Temporal features
Hour of day / day of week (one-hot or cyclic encoding)
Derived features
Ratio estimated_rows / actual_rows (bias indicator)
Predicted selectivity of predicates using histograms
Feature pipelines
Precompute per-query aggregated features over windows (last 1h, 6h, 24h) for stability.
Keep rolling summaries (median, 90th percentile, variance).
Store feature vectors in feature store keyed by query fingerprint and time window.
Labels (what to predict)
Choose target variables that matter:
Latency (ms): regression target. Use log-transform to stabilize variance.
CPU time (ms): regression.
Prob(timeout): binary (timeout > threshold).
Plan regression probability: binary: whether next run will regress relative to previous baseline.
High IO risk: binary classification for heavy I/O queries.
You may model multiple targets (multi-output regression/classification) or separate models.
Model choices
Start simple and iterate:
Baseline models
Gradient Boosted Trees (XGBoost, LightGBM, CatBoost): fast, explainable via SHAP, handle mixed features well. Great baseline for tabular telemetry.
Linear models with interactions for very interpretable baselines.

Join the conversation! Your thoughts help the community grow.