pg-stats 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/queries/bloat.sql +117 -58
- data/queries/blocking-queries.sql +16 -9
- data/queries/cache-hit-rate.sql +5 -4
- data/queries/extensions.sql +7 -1
- data/queries/index-size.sql +15 -8
- data/queries/index-usage.sql +7 -6
- data/queries/locks.sql +10 -6
- data/queries/long-running-queries.sql +3 -3
- data/queries/outliers.sql +23 -8
- data/queries/seq-scans.sql +5 -3
- data/queries/slow-statements.sql +23 -7
- data/queries/table-indexes-size.sql +13 -7
- data/queries/table-size.sql +12 -7
- data/queries/total-index-size.sql +11 -6
- data/queries/total-table-size.sql +12 -7
- data/queries/unused-indexes.sql +12 -5
- data/queries/vacuum.sql +6 -2
- data/scripts/cache-hit-rate.sh +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e621fc8e0c48634775ea2900f893961830848e582a027713de9fb50dbc109da
|
4
|
+
data.tar.gz: 9c10943edee1b52e1ea39e51be577e51c8114e41495b3ad09024426f0500134c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8586306450c8f4efdc01bd19bdd9ca4d057310e4f20928c7da66e35c721e656e9284ee5b958b902d94d2fff05cc6c866ddb2756b57bc42d806a592579fc9885d
|
7
|
+
data.tar.gz: 9675a5a7d7332a7a43d06ac35d8f1f347b5e22362609c995203a89a404ada143b449bb2e7e346de82f4346c377645badacff6896f6d7c2230a3f05e0aeaf5238
|
data/queries/bloat.sql
CHANGED
@@ -1,63 +1,122 @@
|
|
1
1
|
/* Table and index bloat in your database ordered by most wasteful */
|
2
2
|
|
3
|
-
WITH
|
4
|
-
|
5
|
-
), bloat_info AS (
|
6
|
-
SELECT
|
7
|
-
ma,bs,schemaname,tablename,
|
8
|
-
(datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
|
9
|
-
(maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
|
10
|
-
FROM (
|
3
|
+
WITH
|
4
|
+
constants AS (
|
11
5
|
SELECT
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
)
|
6
|
+
current_setting('block_size')::numeric AS bs,
|
7
|
+
23 AS hdr,
|
8
|
+
4 AS ma
|
9
|
+
),
|
10
|
+
bloat_info AS (
|
11
|
+
SELECT
|
12
|
+
ma,
|
13
|
+
bs,
|
14
|
+
schemaname,
|
15
|
+
tablename,
|
16
|
+
(datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
|
17
|
+
(maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
|
18
|
+
FROM (
|
19
|
+
SELECT
|
20
|
+
schemaname,
|
21
|
+
tablename,
|
22
|
+
hdr,
|
23
|
+
ma,
|
24
|
+
bs,
|
25
|
+
SUM((1-null_frac)*avg_width) AS datawidth,
|
26
|
+
MAX(null_frac) AS maxfracsum,
|
27
|
+
hdr+(
|
28
|
+
SELECT
|
29
|
+
1+count(*)/8
|
30
|
+
FROM
|
31
|
+
pg_stats s2
|
32
|
+
WHERE
|
33
|
+
null_frac<>0 AND
|
34
|
+
s2.schemaname = s.schemaname AND
|
35
|
+
s2.tablename = s.tablename
|
36
|
+
) AS nullhdr
|
37
|
+
FROM
|
38
|
+
pg_stats s,
|
39
|
+
constants
|
40
|
+
GROUP BY
|
41
|
+
1,
|
42
|
+
2,
|
43
|
+
3,
|
44
|
+
4,
|
45
|
+
5
|
46
|
+
) AS foo
|
47
|
+
),
|
48
|
+
table_bloat AS (
|
49
|
+
SELECT
|
50
|
+
schemaname,
|
51
|
+
tablename,
|
52
|
+
cc.relpages,
|
53
|
+
bs,
|
54
|
+
CEIL((cc.reltuples*((datahdr+ma-
|
55
|
+
(CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta
|
56
|
+
FROM
|
57
|
+
bloat_info
|
58
|
+
JOIN
|
59
|
+
pg_class cc ON
|
60
|
+
cc.relname = bloat_info.tablename
|
61
|
+
JOIN
|
62
|
+
pg_namespace nn ON
|
63
|
+
cc.relnamespace = nn.oid AND
|
64
|
+
nn.nspname = bloat_info.schemaname AND
|
65
|
+
nn.nspname <> 'information_schema'
|
66
|
+
),
|
67
|
+
index_bloat AS (
|
68
|
+
SELECT
|
69
|
+
schemaname,
|
70
|
+
tablename,
|
71
|
+
bs,
|
72
|
+
COALESCE(c2.relname,'?') AS iname,
|
73
|
+
COALESCE(c2.reltuples,0) AS ituples,
|
74
|
+
COALESCE(c2.relpages,0) AS ipages,
|
75
|
+
COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
|
76
|
+
FROM
|
77
|
+
bloat_info
|
78
|
+
JOIN
|
79
|
+
pg_class cc
|
80
|
+
ON cc.relname = bloat_info.tablename
|
81
|
+
JOIN
|
82
|
+
pg_namespace nn ON
|
83
|
+
cc.relnamespace = nn.oid AND
|
84
|
+
nn.nspname = bloat_info.schemaname AND
|
85
|
+
nn.nspname <> 'information_schema'
|
86
|
+
JOIN
|
87
|
+
pg_index i ON
|
88
|
+
indrelid = cc.oid
|
89
|
+
JOIN
|
90
|
+
pg_class c2 ON
|
91
|
+
c2.oid = i.indexrelid
|
92
|
+
)
|
93
|
+
|
32
94
|
SELECT
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
(
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
FROM
|
61
|
-
index_bloat) bloat_summary
|
62
|
-
ORDER BY raw_waste DESC, bloat DESC;
|
95
|
+
type,
|
96
|
+
schemaname,
|
97
|
+
object_name,
|
98
|
+
bloat,
|
99
|
+
pg_size_pretty(raw_waste) as waste
|
100
|
+
FROM
|
101
|
+
(
|
102
|
+
SELECT
|
103
|
+
'table' as type,
|
104
|
+
schemaname,
|
105
|
+
tablename as object_name,
|
106
|
+
ROUND(CASE WHEN otta=0 THEN 0.0 ELSE table_bloat.relpages/otta::numeric END,1) AS bloat,
|
107
|
+
CASE WHEN relpages < otta THEN '0' ELSE (bs*(table_bloat.relpages-otta)::bigint)::bigint END AS raw_waste
|
108
|
+
FROM
|
109
|
+
table_bloat
|
110
|
+
UNION SELECT
|
111
|
+
'index' as type,
|
112
|
+
schemaname,
|
113
|
+
tablename || '::' || iname as object_name,
|
114
|
+
ROUND(CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS bloat,
|
115
|
+
CASE WHEN ipages < iotta THEN '0' ELSE (bs*(ipages-iotta))::bigint END AS raw_waste
|
116
|
+
FROM
|
117
|
+
index_bloat
|
118
|
+
) bloat_summary
|
119
|
+
ORDER BY
|
120
|
+
raw_waste DESC,
|
121
|
+
bloat DESC;
|
63
122
|
|
@@ -1,16 +1,23 @@
|
|
1
1
|
/* Queries holding locks which other queries are waiting to be released */
|
2
2
|
|
3
|
-
SELECT
|
3
|
+
SELECT
|
4
|
+
bl.pid AS blocked_pid,
|
4
5
|
ka.query AS blocking_statement,
|
5
6
|
now() - ka.query_start AS blocking_duration,
|
6
7
|
kl.pid AS blocking_pid,
|
7
8
|
a.query AS blocked_statement,
|
8
9
|
now() - a.query_start AS blocked_duration
|
9
|
-
FROM
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
FROM
|
11
|
+
pg_catalog.pg_locks bl
|
12
|
+
JOIN
|
13
|
+
pg_catalog.pg_stat_activity a ON
|
14
|
+
bl.pid = a.pid
|
15
|
+
JOIN
|
16
|
+
pg_catalog.pg_locks kl
|
17
|
+
JOIN
|
18
|
+
pg_catalog.pg_stat_activity ka ON
|
19
|
+
kl.pid = ka.pid ON
|
20
|
+
bl.transactionid = kl.transactionid AND
|
21
|
+
bl.pid != kl.pid
|
22
|
+
WHERE
|
23
|
+
NOT bl.granted;
|
data/queries/cache-hit-rate.sql
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
SELECT
|
4
4
|
'index hit rate' AS name,
|
5
5
|
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS ratio
|
6
|
-
FROM
|
7
|
-
|
8
|
-
SELECT
|
6
|
+
FROM
|
7
|
+
pg_statio_user_indexes
|
8
|
+
UNION ALL SELECT
|
9
9
|
'table hit rate' AS name,
|
10
10
|
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS ratio
|
11
|
-
FROM
|
11
|
+
FROM
|
12
|
+
pg_statio_user_tables;
|
data/queries/extensions.sql
CHANGED
data/queries/index-size.sql
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
/* The size of indexes, descending by size */
|
2
2
|
|
3
|
-
SELECT
|
3
|
+
SELECT
|
4
|
+
c.relname AS name,
|
4
5
|
pg_size_pretty(sum(c.relpages::bigint*8192)::bigint) AS size
|
5
|
-
FROM
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
FROM
|
7
|
+
pg_class c
|
8
|
+
LEFT JOIN
|
9
|
+
pg_namespace n ON
|
10
|
+
(n.oid = c.relnamespace)
|
11
|
+
WHERE
|
12
|
+
n.nspname NOT IN ('pg_catalog', 'information_schema') AND
|
13
|
+
n.nspname !~ '^pg_toast' AND
|
14
|
+
c.relkind='i'
|
15
|
+
GROUP BY
|
16
|
+
c.relname
|
17
|
+
ORDER BY
|
18
|
+
sum(c.relpages) DESC;
|
data/queries/index-usage.sql
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
/* Index hit rate (effective databases are at 99% and up) */
|
2
2
|
|
3
|
-
SELECT
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
SELECT
|
4
|
+
relname,
|
5
|
+
CASE idx_scan
|
6
|
+
WHEN 0 THEN 'Insufficient data'
|
7
|
+
ELSE (100 * idx_scan / (seq_scan + idx_scan))::text
|
8
|
+
END percent_of_times_index_used,
|
9
|
+
n_live_tup rows_in_table
|
9
10
|
FROM
|
10
11
|
pg_stat_user_tables
|
11
12
|
ORDER BY
|
data/queries/locks.sql
CHANGED
@@ -8,9 +8,13 @@ SELECT
|
|
8
8
|
pg_locks.mode,
|
9
9
|
pg_stat_activity.query AS query_snippet,
|
10
10
|
age(now(),pg_stat_activity.query_start) AS "age"
|
11
|
-
FROM
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
FROM
|
12
|
+
pg_stat_activity,
|
13
|
+
pg_locks
|
14
|
+
LEFT OUTER JOIN
|
15
|
+
pg_class ON
|
16
|
+
(pg_locks.relation = pg_class.oid)
|
17
|
+
WHERE
|
18
|
+
pg_stat_activity.query <> '<insufficient privilege>' AND
|
19
|
+
pg_locks.pid = pg_stat_activity.pid AND
|
20
|
+
pg_stat_activity.pid <> pg_backend_pid() order by query_start;
|
@@ -7,8 +7,8 @@ SELECT
|
|
7
7
|
FROM
|
8
8
|
pg_stat_activity
|
9
9
|
WHERE
|
10
|
-
pg_stat_activity.query <> ''::text
|
11
|
-
|
12
|
-
|
10
|
+
pg_stat_activity.query <> ''::text AND
|
11
|
+
state <> 'idle' AND
|
12
|
+
now() - pg_stat_activity.query_start > interval '1 minute'
|
13
13
|
ORDER BY
|
14
14
|
now() - pg_stat_activity.query_start DESC;
|
data/queries/outliers.sql
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
/* 10 queries that have longest execution time in aggregate */
|
2
2
|
|
3
|
-
SELECT
|
4
|
-
|
5
|
-
to_char(
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
SELECT
|
4
|
+
interval '1 millisecond' * total_time AS total_exec_time,
|
5
|
+
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%' AS prop_exec_time,
|
6
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
7
|
+
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time,
|
8
|
+
query AS query
|
9
|
+
FROM
|
10
|
+
pg_stat_statements
|
11
|
+
WHERE
|
12
|
+
userid = (
|
13
|
+
SELECT
|
14
|
+
usesysid
|
15
|
+
FROM
|
16
|
+
pg_user
|
17
|
+
WHERE
|
18
|
+
usename = current_user
|
19
|
+
LIMIT
|
20
|
+
1
|
21
|
+
)
|
22
|
+
ORDER BY
|
23
|
+
total_time DESC
|
24
|
+
LIMIT
|
25
|
+
10;
|
data/queries/seq-scans.sql
CHANGED
data/queries/slow-statements.sql
CHANGED
@@ -1,9 +1,25 @@
|
|
1
1
|
/* 10 queries that have longest execution time in aggregate */
|
2
2
|
|
3
|
-
SELECT
|
4
|
-
|
5
|
-
|
6
|
-
to_char(
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
SELECT
|
4
|
+
query AS qry,
|
5
|
+
interval '1 millisecond' * total_time AS exec_time,
|
6
|
+
to_char((total_time/sum(total_time) OVER()) * 100, 'FM90D0') || '%' AS prop_exec_time,
|
7
|
+
to_char(calls, 'FM999G999G990') AS ncalls,
|
8
|
+
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time
|
9
|
+
FROM
|
10
|
+
pg_stat_statements
|
11
|
+
WHERE
|
12
|
+
userid = (
|
13
|
+
SELECT
|
14
|
+
usesysid
|
15
|
+
FROM
|
16
|
+
pg_user
|
17
|
+
WHERE
|
18
|
+
usename = current_user
|
19
|
+
LIMIT
|
20
|
+
1
|
21
|
+
)
|
22
|
+
ORDER BY
|
23
|
+
calls DESC
|
24
|
+
LIMIT
|
25
|
+
10;
|
@@ -1,10 +1,16 @@
|
|
1
1
|
/* Total size of all the indexes on each table, descending by size */
|
2
2
|
|
3
|
-
SELECT
|
3
|
+
SELECT
|
4
|
+
c.relname AS table,
|
4
5
|
pg_size_pretty(pg_indexes_size(c.oid)) AS index_size
|
5
|
-
FROM
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
FROM
|
7
|
+
pg_class c
|
8
|
+
LEFT JOIN
|
9
|
+
pg_namespace n ON
|
10
|
+
(n.oid = c.relnamespace)
|
11
|
+
WHERE
|
12
|
+
n.nspname NOT IN ('pg_catalog', 'information_schema') AND
|
13
|
+
n.nspname !~ '^pg_toast' AND
|
14
|
+
c.relkind='r'
|
15
|
+
ORDER BY
|
16
|
+
pg_indexes_size(c.oid) DESC;
|
data/queries/table-size.sql
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
/* Size of the tables (excluding indexes), descending by size */
|
2
2
|
|
3
|
-
SELECT
|
3
|
+
SELECT
|
4
|
+
c.relname AS name,
|
4
5
|
pg_size_pretty(pg_table_size(c.oid)) AS size
|
5
|
-
FROM
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
FROM
|
7
|
+
pg_class c
|
8
|
+
LEFT JOIN
|
9
|
+
pg_namespace n ON
|
10
|
+
(n.oid = c.relnamespace)
|
11
|
+
WHERE
|
12
|
+
n.nspname NOT IN ('pg_catalog', 'information_schema') AND
|
13
|
+
n.nspname !~ '^pg_toast' AND c.relkind='r'
|
14
|
+
ORDER BY
|
15
|
+
pg_table_size(c.oid) DESC;
|
@@ -1,8 +1,13 @@
|
|
1
1
|
/* Total size of all indexes in MB */
|
2
2
|
|
3
|
-
SELECT
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
SELECT
|
4
|
+
pg_size_pretty(sum(c.relpages::bigint*8192)::bigint) AS size
|
5
|
+
FROM
|
6
|
+
pg_class c
|
7
|
+
LEFT JOIN
|
8
|
+
pg_namespace n ON
|
9
|
+
(n.oid = c.relnamespace)
|
10
|
+
WHERE
|
11
|
+
n.nspname NOT IN ('pg_catalog', 'information_schema') AND
|
12
|
+
n.nspname !~ '^pg_toast' AND
|
13
|
+
c.relkind='i';
|
@@ -1,10 +1,15 @@
|
|
1
1
|
/* Size of the tables (including indexes), descending by size */
|
2
2
|
|
3
|
-
SELECT
|
3
|
+
SELECT
|
4
|
+
c.relname AS name,
|
4
5
|
pg_size_pretty(pg_total_relation_size(c.oid)) AS size
|
5
|
-
FROM
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
FROM
|
7
|
+
pg_class c
|
8
|
+
LEFT JOIN
|
9
|
+
pg_namespace n ON
|
10
|
+
(n.oid = c.relnamespace)
|
11
|
+
WHERE
|
12
|
+
n.nspname NOT IN ('pg_catalog', 'information_schema') AND
|
13
|
+
n.nspname !~ '^pg_toast' AND c.relkind='r'
|
14
|
+
ORDER BY
|
15
|
+
pg_total_relation_size(c.oid) DESC;
|
data/queries/unused-indexes.sql
CHANGED
@@ -9,8 +9,15 @@ SELECT
|
|
9
9
|
indexrelname AS index,
|
10
10
|
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
|
11
11
|
idx_scan as index_scans
|
12
|
-
FROM
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
FROM
|
13
|
+
pg_stat_user_indexes ui
|
14
|
+
JOIN
|
15
|
+
pg_index i ON
|
16
|
+
ui.indexrelid = i.indexrelid
|
17
|
+
WHERE
|
18
|
+
NOT indisunique AND
|
19
|
+
idx_scan < 50 AND
|
20
|
+
pg_relation_size(relid) > 5 * 8192
|
21
|
+
ORDER BY
|
22
|
+
pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,
|
23
|
+
pg_relation_size(i.indexrelid) DESC;
|
data/queries/vacuum.sql
CHANGED
@@ -35,6 +35,10 @@ SELECT
|
|
35
35
|
THEN 'yes'
|
36
36
|
END AS expect_autovacuum
|
37
37
|
FROM
|
38
|
-
pg_stat_user_tables psut INNER JOIN
|
39
|
-
|
38
|
+
pg_stat_user_tables psut INNER JOIN
|
39
|
+
pg_class ON
|
40
|
+
psut.relid = pg_class.oid
|
41
|
+
INNER JOIN
|
42
|
+
vacuum_settings ON
|
43
|
+
pg_class.oid = vacuum_settings.oid
|
40
44
|
ORDER BY 1;
|
data/scripts/cache-hit-rate.sh
CHANGED