Skip to content

Commit 8790fe5

Browse files
committed
more high level checks
1 parent 54e76a7 commit 8790fe5

File tree

4 files changed

+253
-1
lines changed

4 files changed

+253
-1
lines changed

pgFirstAid.sql

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,85 @@ select
913913
3 as severity_order
914914
from
915915
lw;
916+
-- MEDIUM: High calls low value queries
917+
insert
918+
into
919+
health_results
920+
select
921+
'MEDIUM' as severity,
922+
'Query Health' as category,
923+
'High Calls Low Value Queries' as check_name,
924+
'queryid: ' || pss.queryid::text as object_name,
925+
'Very high call volume with low per-call value can create avoidable overhead and crowd out expensive work' as issue_description,
926+
'calls: ' || pss.calls || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 3) ||
927+
', total_exec_time_ms: ' || round(pss.total_exec_time::numeric, 2) ||
928+
', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
929+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
930+
'Batch repeated requests, cache stable lookups, and reduce N+1 query patterns in the application layer' as recommended_action,
931+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
932+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
933+
3 as severity_order
934+
from
935+
pg_stat_statements pss
936+
where
937+
pss.calls >= 5000
938+
and pss.mean_exec_time <= 2
939+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) <= 2
940+
order by
941+
pss.calls desc
942+
limit 10;
943+
-- MEDIUM: High rows per call queries
944+
insert
945+
into
946+
health_results
947+
select
948+
'MEDIUM' as severity,
949+
'Query Health' as category,
950+
'High Rows Per Call Queries' as check_name,
951+
'queryid: ' || pss.queryid::text as object_name,
952+
'High rows returned per execution often indicates over-fetching or missing selective filters' as issue_description,
953+
'calls: ' || pss.calls || ', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
954+
', total_rows: ' || pss.rows || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
955+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
956+
'Add tighter predicates, pagination, and narrower SELECT lists to reduce unnecessary row transfer' as recommended_action,
957+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
958+
https://www.postgresql.org/docs/current/queries-limit.html \
959+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
960+
3 as severity_order
961+
from
962+
pg_stat_statements pss
963+
where
964+
pss.calls >= 20
965+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) > 10000
966+
order by
967+
(pss.rows::numeric / NULLIF(pss.calls, 0)) desc
968+
limit 10;
969+
-- MEDIUM: High shared block reads per call queries
970+
insert
971+
into
972+
health_results
973+
select
974+
'MEDIUM' as severity,
975+
'Query Health' as category,
976+
'High Shared Block Reads Per Call Queries' as check_name,
977+
'queryid: ' || pss.queryid::text as object_name,
978+
'High shared block reads per call usually points to heavy table or index scans and poor locality' as issue_description,
979+
'calls: ' || pss.calls || ', shared_blks_read_per_call: ' || round((pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)), 2) ||
980+
', shared_blks_read: ' || pss.shared_blks_read || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
981+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
982+
'Use EXPLAIN (ANALYZE, BUFFERS) to add selective indexes and reduce pages read per execution' as recommended_action,
983+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
984+
https://www.postgresql.org/docs/current/using-explain.html \
985+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
986+
3 as severity_order
987+
from
988+
pg_stat_statements pss
989+
where
990+
pss.calls >= 20
991+
and (pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) > 1000
992+
order by
993+
(pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) desc
994+
limit 10;
916995
-- LOW: Missing indexes on foreign keys
917996
insert
918997
into

testing/pgTAP/03_high_tests.sql

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
BEGIN;
2-
SELECT plan(30);
2+
SELECT plan(36);
33

44
SELECT ok(
55
(SELECT count(*) >= 0 FROM pg_firstAid() WHERE check_name = 'Current Blocked/Blocking Queries'),
@@ -109,6 +109,33 @@ SELECT ok(
109109
'View executes Lock-Wait-Heavy Active Queries check'
110110
);
111111

112+
SELECT ok(
113+
(SELECT count(*) >= 0 FROM pg_firstAid() WHERE check_name = 'High Calls Low Value Queries'),
114+
'Function executes High Calls Low Value Queries check'
115+
);
116+
SELECT ok(
117+
(SELECT count(*) >= 0 FROM v_pgfirstaid WHERE check_name = 'High Calls Low Value Queries'),
118+
'View executes High Calls Low Value Queries check'
119+
);
120+
121+
SELECT ok(
122+
(SELECT count(*) >= 0 FROM pg_firstAid() WHERE check_name = 'High Rows Per Call Queries'),
123+
'Function executes High Rows Per Call Queries check'
124+
);
125+
SELECT ok(
126+
(SELECT count(*) >= 0 FROM v_pgfirstaid WHERE check_name = 'High Rows Per Call Queries'),
127+
'View executes High Rows Per Call Queries check'
128+
);
129+
130+
SELECT ok(
131+
(SELECT count(*) >= 0 FROM pg_firstAid() WHERE check_name = 'High Shared Block Reads Per Call Queries'),
132+
'Function executes High Shared Block Reads Per Call Queries check'
133+
);
134+
SELECT ok(
135+
(SELECT count(*) >= 0 FROM v_pgfirstaid WHERE check_name = 'High Shared Block Reads Per Call Queries'),
136+
'View executes High Shared Block Reads Per Call Queries check'
137+
);
138+
112139
SELECT ok(
113140
(SELECT count(*) >= 0 FROM pg_firstAid() WHERE check_name = 'Table with more than 50 columns'),
114141
'Function executes Table with more than 50 columns check'

view_pgFirstAid.sql

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,79 @@ select
839839
from
840840
lw)
841841
union all
842+
-- MEDIUM: High calls low value queries
843+
select
844+
'MEDIUM' as severity,
845+
'Query Health' as category,
846+
'High Calls Low Value Queries' as check_name,
847+
'queryid: ' || pss.queryid::text as object_name,
848+
'Very high call volume with low per-call value can create avoidable overhead and crowd out expensive work' as issue_description,
849+
'calls: ' || pss.calls || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 3) ||
850+
', total_exec_time_ms: ' || round(pss.total_exec_time::numeric, 2) ||
851+
', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
852+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
853+
'Batch repeated requests, cache stable lookups, and reduce N+1 query patterns in the application layer' as recommended_action,
854+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
855+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
856+
3 as severity_order
857+
from
858+
pg_stat_statements pss
859+
where
860+
pss.calls >= 5000
861+
and pss.mean_exec_time <= 2
862+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) <= 2
863+
order by
864+
pss.calls desc
865+
limit 10
866+
union all
867+
-- MEDIUM: High rows per call queries
868+
select
869+
'MEDIUM' as severity,
870+
'Query Health' as category,
871+
'High Rows Per Call Queries' as check_name,
872+
'queryid: ' || pss.queryid::text as object_name,
873+
'High rows returned per execution often indicates over-fetching or missing selective filters' as issue_description,
874+
'calls: ' || pss.calls || ', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
875+
', total_rows: ' || pss.rows || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
876+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
877+
'Add tighter predicates, pagination, and narrower SELECT lists to reduce unnecessary row transfer' as recommended_action,
878+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
879+
https://www.postgresql.org/docs/current/queries-limit.html \
880+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
881+
3 as severity_order
882+
from
883+
pg_stat_statements pss
884+
where
885+
pss.calls >= 20
886+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) > 10000
887+
order by
888+
(pss.rows::numeric / NULLIF(pss.calls, 0)) desc
889+
limit 10
890+
union all
891+
-- MEDIUM: High shared block reads per call queries
892+
select
893+
'MEDIUM' as severity,
894+
'Query Health' as category,
895+
'High Shared Block Reads Per Call Queries' as check_name,
896+
'queryid: ' || pss.queryid::text as object_name,
897+
'High shared block reads per call usually points to heavy table or index scans and poor locality' as issue_description,
898+
'calls: ' || pss.calls || ', shared_blks_read_per_call: ' || round((pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)), 2) ||
899+
', shared_blks_read: ' || pss.shared_blks_read || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
900+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
901+
'Use EXPLAIN (ANALYZE, BUFFERS) to add selective indexes and reduce pages read per execution' as recommended_action,
902+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
903+
https://www.postgresql.org/docs/current/using-explain.html \
904+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
905+
3 as severity_order
906+
from
907+
pg_stat_statements pss
908+
where
909+
pss.calls >= 20
910+
and (pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) > 1000
911+
order by
912+
(pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) desc
913+
limit 10
914+
union all
842915
-- LOW: Roles that have never logged in (with LOGIN rights)
843916
(WITH ur AS (
844917
SELECT

view_pgFirstAid_managed.sql

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,79 @@ select
833833
from
834834
lw)
835835
union all
836+
-- MEDIUM: High calls low value queries
837+
select
838+
'MEDIUM' as severity,
839+
'Query Health' as category,
840+
'High Calls Low Value Queries' as check_name,
841+
'queryid: ' || pss.queryid::text as object_name,
842+
'Very high call volume with low per-call value can create avoidable overhead and crowd out expensive work' as issue_description,
843+
'calls: ' || pss.calls || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 3) ||
844+
', total_exec_time_ms: ' || round(pss.total_exec_time::numeric, 2) ||
845+
', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
846+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
847+
'Batch repeated requests, cache stable lookups, and reduce N+1 query patterns in the application layer' as recommended_action,
848+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
849+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
850+
3 as severity_order
851+
from
852+
pg_stat_statements pss
853+
where
854+
pss.calls >= 5000
855+
and pss.mean_exec_time <= 2
856+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) <= 2
857+
order by
858+
pss.calls desc
859+
limit 10
860+
union all
861+
-- MEDIUM: High rows per call queries
862+
select
863+
'MEDIUM' as severity,
864+
'Query Health' as category,
865+
'High Rows Per Call Queries' as check_name,
866+
'queryid: ' || pss.queryid::text as object_name,
867+
'High rows returned per execution often indicates over-fetching or missing selective filters' as issue_description,
868+
'calls: ' || pss.calls || ', rows_per_call: ' || round((pss.rows::numeric / NULLIF(pss.calls, 0)), 2) ||
869+
', total_rows: ' || pss.rows || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
870+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
871+
'Add tighter predicates, pagination, and narrower SELECT lists to reduce unnecessary row transfer' as recommended_action,
872+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
873+
https://www.postgresql.org/docs/current/queries-limit.html \
874+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
875+
3 as severity_order
876+
from
877+
pg_stat_statements pss
878+
where
879+
pss.calls >= 20
880+
and (pss.rows::numeric / NULLIF(pss.calls, 0)) > 10000
881+
order by
882+
(pss.rows::numeric / NULLIF(pss.calls, 0)) desc
883+
limit 10
884+
union all
885+
-- MEDIUM: High shared block reads per call queries
886+
select
887+
'MEDIUM' as severity,
888+
'Query Health' as category,
889+
'High Shared Block Reads Per Call Queries' as check_name,
890+
'queryid: ' || pss.queryid::text as object_name,
891+
'High shared block reads per call usually points to heavy table or index scans and poor locality' as issue_description,
892+
'calls: ' || pss.calls || ', shared_blks_read_per_call: ' || round((pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)), 2) ||
893+
', shared_blks_read: ' || pss.shared_blks_read || ', mean_exec_time_ms: ' || round(pss.mean_exec_time::numeric, 2) ||
894+
', query: ' || left(regexp_replace(pss.query, E'[\n\r\t]+', ' ', 'g'), 350) as current_value,
895+
'Use EXPLAIN (ANALYZE, BUFFERS) to add selective indexes and reduce pages read per execution' as recommended_action,
896+
'https://www.postgresql.org/docs/current/pgstatstatements.html \
897+
https://www.postgresql.org/docs/current/using-explain.html \
898+
https://www.tigerdata.com/blog/using-pg-stat-statements-to-optimize-queries' as documentation_link,
899+
3 as severity_order
900+
from
901+
pg_stat_statements pss
902+
where
903+
pss.calls >= 20
904+
and (pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) > 1000
905+
order by
906+
(pss.shared_blks_read::numeric / NULLIF(pss.calls, 0)) desc
907+
limit 10
908+
union all
836909
-- LOW: Roles that have never logged in (with LOGIN rights)
837910
(WITH ur AS (
838911
SELECT

0 commit comments

Comments
 (0)