Skip to content

Instantly share code, notes, and snippets.

@coryodaniel
Created January 20, 2018 01:17
Show Gist options
  • Save coryodaniel/ec132d1655b08717e4816cc4bd109795 to your computer and use it in GitHub Desktop.
Save coryodaniel/ec132d1655b08717e4816cc4bd109795 to your computer and use it in GitHub Desktop.
PG Stat Statements helpers
\set common_pct 0.1
\set common_slow 10
\set other_slow 100
CREATE MATERIALIZED VIEW v_pg_stat_statements AS
WITH totals AS (
SELECT sum(calls) as ttl_calls, sum(total_time) as ttl_time
FROM pg_stat_statements
)
SELECT
userid,
dbid,
queryid,
-- shorten and clean up the query field
substr(REGEXP_REPLACE(regexp_replace(query, '[ \t\n]+', ' ', 'g'), '^\s+|\s+$', ''), 1, 128) as short,
-- Clean up the query field
REGEXP_REPLACE(regexp_replace(query, '[ \t\n]+', ' ', 'g'), '^\s+|\s+$', '') as query,
calls,
total_time,
min_time,
max_time,
mean_time,
stddev_time,
rows,
shared_blks_hit,
shared_blks_read,
-- read comes from disk, hit comes from cache
-- Shared blocks contain data from regular tables and indexes;
-- local blocks contain data from temporary tables and indexes;
-- cache hit rate: should be close to 1
CASE
WHEN (shared_blks_hit + shared_blks_read)::float = 0 THEN 0
ELSE shared_blks_hit / (shared_blks_hit + shared_blks_read)::float
END as hit_rate,
shared_blks_dirtied,
shared_blks_written,
local_blks_hit,
local_blks_read,
local_blks_dirtied,
local_blks_written,
temp_blks_read,
temp_blks_written,
blk_read_time,
blk_write_time,
-- how many bytes of query text (not results) have been sent over the wire
pg_size_pretty((calls*pg_column_size(query))::bigint) as query_bandwidth,
(calls / totals.ttl_calls) AS pct_of_calls,
(total_time / totals.ttl_time) AS pct_of_time
FROM pg_stat_statements, totals;
CREATE VIEW v_reads_pg_stat_statements AS
SELECT *
FROM v_pg_stat_statements
WHERE short ILIKE 'SELECT%' OR short ILIKE 'WITH%';
CREATE VIEW v_common_queries AS
SELECT *
FROM (
SELECT percent_rank() OVER (ORDER BY calls DESC) AS pct, *
FROM v_reads_pg_stat_statements
) AS ranked
WHERE pct <= :common_pct
ORDER BY calls DESC;
CREATE OR REPLACE VIEW v_slow_common_queries AS
SELECT *
FROM v_common_queries
WHERE mean_time > :common_slow
OR stddev_time > :common_slow
ORDER BY calls DESC;
CREATE OR REPLACE VIEW v_slow_other_queries AS
SELECT *
FROM v_reads_pg_stat_statements
WHERE mean_time > :other_slow
OR stddev_time > :other_slow
ORDER BY calls DESC;
CREATE OR REPLACE VIEW v_most_variance AS
SELECT *
FROM (
SELECT percent_rank() OVER (ORDER BY stddev_time DESC) AS pct, *
FROM v_reads_pg_stat_statements
) AS ranked
WHERE pct <= :common_pct
ORDER BY stddev_time DESC;
-- CREATE OR REPLACE FUNCTION pss_common_queries(IN max_pct float)
-- RETURNS TABLE (queryid bigint, pct double precision, calls bigint, total_time double precision) AS
-- $BODY$
-- BEGIN
-- return query
-- SELECT ranked.queryid, ranked.pct, ranked.calls, ranked.total_time
-- FROM (
-- SELECT percent_rank() OVER (ORDER BY vr.calls DESC) AS pct, *
-- FROM v_reads_pg_stat_statements AS vr
-- ) AS ranked
-- WHERE ranked.pct <= max_pct
-- ORDER BY total_time DESC;
-- END;
-- $BODY$
-- LANGUAGE plpgsql VOLATILE;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment