diff --git a/docker-compose.yml b/docker-compose.yml index a9add3fb8..05e8ed510 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -540,6 +540,17 @@ services: # (concrete pin, active watch) from being dropped. image: postgres:16.15-alpine container_name: healthlog-db + # Loads pg_stat_statements so slow queries can be found from measurements + # instead of guesses. Loading the library only collects statistics; the + # view appears after a one-time `CREATE EXTENSION pg_stat_statements;` + # (docs/ops/query-statistics.md). Changing this line restarts the + # database once on the next `compose up`. + command: + - postgres + - -c + - shared_preload_libraries=pg_stat_statements + - -c + - pg_stat_statements.track=top # cap_drop: [ALL] is deliberately NOT applied here (unlike `app`): the # official Postgres entrypoint starts as root, chowns the data # directory, and drops privileges to the `postgres` user itself, which diff --git a/docs/ops/query-statistics.md b/docs/ops/query-statistics.md new file mode 100644 index 000000000..6689898af --- /dev/null +++ b/docs/ops/query-statistics.md @@ -0,0 +1,29 @@ +# Query statistics (pg_stat_statements) + +From v1.42 the bundled database loads the `pg_stat_statements` library, so the time spent in each query shape can be read from the database itself. Loading the library only collects statistics in shared memory; nothing is sent anywhere. + +## Enable the view + +The library is loaded through the `command:` of the `db` service in `docker-compose.yml`. The first `docker compose up` after updating restarts the database once. Then create the extension once: + +```sh +docker compose exec db psql -U healthlog -d healthlog -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;" +``` + +## Read it + +The slowest query shapes by total time: + +```sh +docker compose exec db psql -U healthlog -d healthlog -c "SELECT calls, round(total_exec_time) AS total_ms, round(mean_exec_time, 1) AS mean_ms, left(query, 120) AS query FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 15;" +``` + +The statements are stored with their parameters replaced by placeholders, so values from your records do not appear in the view. + +## Reset + +```sh +docker compose exec db psql -U healthlog -d healthlog -c "SELECT pg_stat_statements_reset();" +``` + +If you run your own PostgreSQL instead of the bundled one, add `pg_stat_statements` to `shared_preload_libraries` in its configuration and restart it before creating the extension.