Database field guide · 19
Database Observability
Sessions, waits, plans, and workload time
Connect requests to active sessions, wait events, runtime plans, statement aggregates, and historical workload evidence.
Franck Pachot7 chapterswait events · active sessions · runtime evidence
Build the mental model before choosing the mechanism.
This minibook was AI-generated from Franck Pachot's archived blog posts. Links to the original articles are included for source context and verification.
01
Observe time, not dashboard color
Database response time divides into CPU execution and waits for resources or coordination. A useful signal preserves how many sessions experienced each state and for how long.
- Elapsed time includes work outside the database.
- Wait names identify a phase, not always a cause.
- Concurrency turns small per-call costs into saturation.
02
Active sessions are samples
Active Session History samples sessions running on CPU or waiting in a database call. Aggregating samples approximates database time by SQL, event, module, object, or plan line.
- ASH is statistical, not a complete trace.
- Sample counts need the sampling interval for time estimates.
- Idle sessions are intentionally absent.
03
Current activity is a snapshot
V$SESSION and pg_stat_activity show present session state. Repeated sampling can reconstruct a short history, but transaction age and prior statements require explicit capture.
- Record backend and application identity.
- Query start and transaction start answer different questions.
- Distributed systems require collection from all nodes.
04
Plans need runtime counters
A plan explains operators; actual rows, loops, buffers, spills, and waits explain execution. Statement aggregates hide skew unless parameter and plan identity are retained.
- Find the first estimate divergence.
- Multiply per-loop rows by loops.
- Correlate plan changes with workload and schema changes.
05
Tag the business request
SQL text alone cannot distinguish checkout from reconciliation or retries from first attempts. Module, action, application_name, trace identifiers, and query comments connect database work to its caller.
- Use bounded-cardinality tags.
- Propagate identity through connection pools.
- Keep secrets and user data out of SQL comments.
06
Investigate with a time window
Start from an incident interval, quantify database demand, split CPU from waits, rank dimensions, and only then inspect representative statements and blockers.
- Compare against a workload-matched baseline.
- Preserve evidence before terminating sessions.
- Finish with a falsifiable cause and a monitored change.
07
Field manual
Concrete mechanics, diagnostic evidence, and executable patterns to carry into a real system.
01
Sample PostgreSQL activity
Current activity becomes useful history when sampled with timestamps, transaction age, wait classification, SQL identity, and application metadata.
SELECT clock_timestamp(), pid, application_name, query_id, state,
wait_event_type, wait_event, xact_start, query_start
FROM pg_stat_activity WHERE backend_type='client backend';
02
Rank statement resources
pg_stat_statements aggregates normalized queries. Calls and variance context matter: a high total can be harmless throughput while one spill-heavy call breaks latency.
SELECT queryid, calls, total_exec_time, mean_exec_time, rows,
shared_blks_read, temp_blks_written, wal_bytes
FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 20;
03
Aggregate Oracle ASH
ASH samples active sessions. Converting samples to approximate active-session count requires dividing by samples per second and preserving plan line or wait class dimensions.
SELECT sql_id, session_state, wait_class, event, COUNT(*) samples
FROM v$active_session_history
WHERE sample_time >= systimestamp - interval '15' minute
GROUP BY sql_id, session_state, wait_class, event
ORDER BY samples DESC FETCH FIRST 20 ROWS ONLY;
04
Tag requests at connection boundaries
Set low-cardinality application identity when a pooled connection is borrowed, then clear or replace it before reuse. This turns database evidence into an application workflow.
-- PostgreSQL
SET application_name = 'checkout/payment';
-- Oracle
BEGIN dbms_application_info.set_module('checkout','payment'); END;
/
08
Source articles
Optional deep dives with the complete experiments and product-version context behind this guide.