pg_peek 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +217 -0
- data/Rakefile +16 -0
- data/app/assets/javascripts/pg_peek/application.js +147 -0
- data/app/assets/stylesheets/pg_peek/application.css +362 -0
- data/app/controllers/pg_peek/activity_controller.rb +16 -0
- data/app/controllers/pg_peek/application_controller.rb +36 -0
- data/app/controllers/pg_peek/databases_controller.rb +96 -0
- data/app/controllers/pg_peek/endpoints_controller.rb +10 -0
- data/app/controllers/pg_peek/indexes_controller.rb +7 -0
- data/app/controllers/pg_peek/jobs_controller.rb +44 -0
- data/app/controllers/pg_peek/pg_stat_statements_controller.rb +11 -0
- data/app/controllers/pg_peek/queries_controller.rb +13 -0
- data/app/controllers/pg_peek/tables_controller.rb +6 -0
- data/app/helpers/pg_peek/application_helper.rb +179 -0
- data/app/helpers/pg_peek/report_helper.rb +58 -0
- data/app/jobs/pg_peek/application_job.rb +4 -0
- data/app/mailers/pg_peek/application_mailer.rb +6 -0
- data/app/models/pg_peek/application_record.rb +3 -0
- data/app/models/pg_peek/database.rb +131 -0
- data/app/models/pg_peek/pg_stat_statements.rb +132 -0
- data/app/models/pg_peek/sql_comment.rb +25 -0
- data/app/models/pg_peek/table.rb +266 -0
- data/app/queries/pg_peek/pg14/activity/sessions.sql +26 -0
- data/app/queries/pg_peek/pg14/activity/summary.sql +8 -0
- data/app/queries/pg_peek/pg14/activity/waiting_locks.sql +11 -0
- data/app/queries/pg_peek/pg14/database/vitals.sql +11 -0
- data/app/queries/pg_peek/pg14/indexes/all.sql +17 -0
- data/app/queries/pg_peek/pg14/pg_stat_statements/endpoints.sql +43 -0
- data/app/queries/pg_peek/pg14/pg_stat_statements/jobs.sql +12 -0
- data/app/queries/pg_peek/pg14/pg_stat_statements/outliers.sql +13 -0
- data/app/queries/pg_peek/pg14/pg_stat_statements/outliers_by_job.sql +14 -0
- data/app/queries/pg_peek/pg14/tables/dead_tuples.sql +11 -0
- data/app/queries/pg_peek/pg14/tables/inline_stats.sql +9 -0
- data/app/queries/pg_peek/pg14/tables/stats.sql +32 -0
- data/app/queries/pg_peek/pg15/activity/sessions.sql +26 -0
- data/app/queries/pg_peek/pg15/activity/summary.sql +8 -0
- data/app/queries/pg_peek/pg15/activity/waiting_locks.sql +11 -0
- data/app/queries/pg_peek/pg15/database/vitals.sql +11 -0
- data/app/queries/pg_peek/pg15/indexes/all.sql +17 -0
- data/app/queries/pg_peek/pg15/pg_stat_statements/endpoints.sql +43 -0
- data/app/queries/pg_peek/pg15/pg_stat_statements/jobs.sql +12 -0
- data/app/queries/pg_peek/pg15/pg_stat_statements/outliers.sql +13 -0
- data/app/queries/pg_peek/pg15/pg_stat_statements/outliers_by_job.sql +14 -0
- data/app/queries/pg_peek/pg15/tables/dead_tuples.sql +11 -0
- data/app/queries/pg_peek/pg15/tables/inline_stats.sql +9 -0
- data/app/queries/pg_peek/pg15/tables/stats.sql +32 -0
- data/app/queries/pg_peek/pg16/activity/sessions.sql +26 -0
- data/app/queries/pg_peek/pg16/activity/summary.sql +8 -0
- data/app/queries/pg_peek/pg16/activity/waiting_locks.sql +11 -0
- data/app/queries/pg_peek/pg16/database/vitals.sql +11 -0
- data/app/queries/pg_peek/pg16/indexes/all.sql +17 -0
- data/app/queries/pg_peek/pg16/pg_stat_statements/endpoints.sql +43 -0
- data/app/queries/pg_peek/pg16/pg_stat_statements/jobs.sql +12 -0
- data/app/queries/pg_peek/pg16/pg_stat_statements/outliers.sql +13 -0
- data/app/queries/pg_peek/pg16/pg_stat_statements/outliers_by_job.sql +14 -0
- data/app/queries/pg_peek/pg16/tables/dead_tuples.sql +11 -0
- data/app/queries/pg_peek/pg16/tables/inline_stats.sql +9 -0
- data/app/queries/pg_peek/pg16/tables/stats.sql +32 -0
- data/app/queries/pg_peek/pg17/activity/sessions.sql +26 -0
- data/app/queries/pg_peek/pg17/activity/summary.sql +8 -0
- data/app/queries/pg_peek/pg17/activity/waiting_locks.sql +11 -0
- data/app/queries/pg_peek/pg17/database/vitals.sql +11 -0
- data/app/queries/pg_peek/pg17/indexes/all.sql +17 -0
- data/app/queries/pg_peek/pg17/pg_stat_statements/endpoints.sql +43 -0
- data/app/queries/pg_peek/pg17/pg_stat_statements/jobs.sql +12 -0
- data/app/queries/pg_peek/pg17/pg_stat_statements/outliers.sql +13 -0
- data/app/queries/pg_peek/pg17/pg_stat_statements/outliers_by_job.sql +14 -0
- data/app/queries/pg_peek/pg17/tables/dead_tuples.sql +11 -0
- data/app/queries/pg_peek/pg17/tables/inline_stats.sql +9 -0
- data/app/queries/pg_peek/pg17/tables/stats.sql +32 -0
- data/app/queries/pg_peek/pg18/activity/sessions.sql +26 -0
- data/app/queries/pg_peek/pg18/activity/summary.sql +8 -0
- data/app/queries/pg_peek/pg18/activity/waiting_locks.sql +11 -0
- data/app/queries/pg_peek/pg18/database/vitals.sql +11 -0
- data/app/queries/pg_peek/pg18/indexes/all.sql +17 -0
- data/app/queries/pg_peek/pg18/pg_stat_statements/endpoints.sql +43 -0
- data/app/queries/pg_peek/pg18/pg_stat_statements/jobs.sql +12 -0
- data/app/queries/pg_peek/pg18/pg_stat_statements/outliers.sql +13 -0
- data/app/queries/pg_peek/pg18/pg_stat_statements/outliers_by_job.sql +14 -0
- data/app/queries/pg_peek/pg18/tables/dead_tuples.sql +11 -0
- data/app/queries/pg_peek/pg18/tables/inline_stats.sql +9 -0
- data/app/queries/pg_peek/pg18/tables/stats.sql +32 -0
- data/app/reports/pg_peek/column.rb +27 -0
- data/app/reports/pg_peek/report.rb +63 -0
- data/app/reports/pg_peek/reports/blocked.rb +60 -0
- data/app/reports/pg_peek/reports/databases.rb +47 -0
- data/app/reports/pg_peek/reports/endpoints.rb +35 -0
- data/app/reports/pg_peek/reports/indexes.rb +44 -0
- data/app/reports/pg_peek/reports/job_queries.rb +14 -0
- data/app/reports/pg_peek/reports/jobs.rb +21 -0
- data/app/reports/pg_peek/reports/queries.rb +23 -0
- data/app/reports/pg_peek/reports/sessions.rb +88 -0
- data/app/reports/pg_peek/reports/tables.rb +25 -0
- data/app/views/layouts/pg_peek/application.html.erb +56 -0
- data/app/views/pg_peek/activity/show.html.erb +70 -0
- data/app/views/pg_peek/authentication_required.html.erb +31 -0
- data/app/views/pg_peek/databases/index.html.erb +43 -0
- data/app/views/pg_peek/databases/show.html.erb +169 -0
- data/app/views/pg_peek/endpoints/index.html.erb +24 -0
- data/app/views/pg_peek/indexes/index.html.erb +31 -0
- data/app/views/pg_peek/jobs/index.html.erb +51 -0
- data/app/views/pg_peek/jobs/show.html.erb +17 -0
- data/app/views/pg_peek/pg_stat_statements/_preload_instructions.html.erb +17 -0
- data/app/views/pg_peek/pg_stat_statements/not_preloaded.html.erb +5 -0
- data/app/views/pg_peek/queries/index.html.erb +10 -0
- data/app/views/pg_peek/reports/_report.html.erb +32 -0
- data/app/views/pg_peek/tables/show.html.erb +128 -0
- data/config/routes.rb +16 -0
- data/lib/generators/pg_peek/install/install_generator.rb +40 -0
- data/lib/generators/pg_peek/install/templates/README +31 -0
- data/lib/generators/pg_peek/install/templates/initializer.rb +38 -0
- data/lib/pg_peek/configuration.rb +59 -0
- data/lib/pg_peek/engine.rb +7 -0
- data/lib/pg_peek/query_loader.rb +59 -0
- data/lib/pg_peek/version.rb +3 -0
- data/lib/pg_peek.rb +10 -0
- data/lib/tasks/pg_peek_tasks.rake +4 -0
- metadata +192 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
t.relname AS table_name,
|
|
3
|
+
t.seq_scan,
|
|
4
|
+
t.seq_tup_read,
|
|
5
|
+
t.idx_scan,
|
|
6
|
+
t.idx_tup_fetch,
|
|
7
|
+
t.n_tup_ins,
|
|
8
|
+
t.n_tup_upd,
|
|
9
|
+
t.n_tup_del,
|
|
10
|
+
t.n_live_tup,
|
|
11
|
+
t.n_dead_tup,
|
|
12
|
+
t.last_vacuum,
|
|
13
|
+
t.last_autovacuum,
|
|
14
|
+
t.last_analyze,
|
|
15
|
+
t.last_autoanalyze,
|
|
16
|
+
t.vacuum_count,
|
|
17
|
+
t.autovacuum_count,
|
|
18
|
+
t.analyze_count,
|
|
19
|
+
t.autoanalyze_count,
|
|
20
|
+
s.heap_blks_read,
|
|
21
|
+
s.heap_blks_hit,
|
|
22
|
+
s.idx_blks_read,
|
|
23
|
+
s.idx_blks_hit,
|
|
24
|
+
s.toast_blks_read,
|
|
25
|
+
s.toast_blks_hit,
|
|
26
|
+
s.tidx_blks_read,
|
|
27
|
+
s.tidx_blks_hit,
|
|
28
|
+
c.reltuples AS row_estimate
|
|
29
|
+
FROM pg_stat_user_tables t
|
|
30
|
+
LEFT JOIN pg_statio_user_tables s ON t.relid = s.relid
|
|
31
|
+
LEFT JOIN pg_class c ON t.relid = c.oid
|
|
32
|
+
WHERE t.relname = $1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Client sessions on the current database, except the one asking. Every
|
|
2
|
+
-- duration is taken from one clock reading, so they agree with each other;
|
|
3
|
+
-- clock_timestamp() rather than now() because the reader may be inside a
|
|
4
|
+
-- long transaction of its own.
|
|
5
|
+
SELECT
|
|
6
|
+
pid,
|
|
7
|
+
usename,
|
|
8
|
+
application_name,
|
|
9
|
+
client_addr::text AS client_addr,
|
|
10
|
+
state,
|
|
11
|
+
wait_event_type,
|
|
12
|
+
wait_event,
|
|
13
|
+
backend_start,
|
|
14
|
+
xact_start,
|
|
15
|
+
query_start,
|
|
16
|
+
state_change,
|
|
17
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - query_start)))::bigint AS query_ms,
|
|
18
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - xact_start)))::bigint AS xact_ms,
|
|
19
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - state_change)))::bigint AS state_ms,
|
|
20
|
+
array_to_string(pg_blocking_pids(pid), ',') AS blocked_by,
|
|
21
|
+
query
|
|
22
|
+
FROM pg_stat_activity
|
|
23
|
+
WHERE datname = current_database()
|
|
24
|
+
AND backend_type = 'client backend'
|
|
25
|
+
AND pid <> pg_backend_pid()
|
|
26
|
+
ORDER BY pid
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Server-wide connection use. max_connections is a cluster setting, so the
|
|
2
|
+
-- count spans every database. current_user is who pg_peek connects as, for
|
|
3
|
+
-- the hint about hidden query text.
|
|
4
|
+
SELECT
|
|
5
|
+
current_setting('max_connections')::int AS max_connections,
|
|
6
|
+
count(*) FILTER (WHERE backend_type = 'client backend') AS client_connections,
|
|
7
|
+
current_user AS username
|
|
8
|
+
FROM pg_stat_activity
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- What each waiting session is waiting for. A backend waits for at most one
|
|
2
|
+
-- lock at a time, so pid identifies the row. Relations from other databases
|
|
3
|
+
-- render as a bare oid, which the caller filters out by pid anyway.
|
|
4
|
+
SELECT
|
|
5
|
+
pid,
|
|
6
|
+
locktype,
|
|
7
|
+
mode,
|
|
8
|
+
CASE WHEN relation IS NOT NULL THEN relation::regclass::text END AS relation
|
|
9
|
+
FROM pg_locks
|
|
10
|
+
WHERE NOT granted
|
|
11
|
+
AND pid <> pg_backend_pid()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- One row of health figures for the current database.
|
|
2
|
+
SELECT
|
|
3
|
+
round(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 1) AS cache_hit_ratio,
|
|
4
|
+
numbackends AS connections,
|
|
5
|
+
xact_commit,
|
|
6
|
+
xact_rollback,
|
|
7
|
+
deadlocks,
|
|
8
|
+
temp_files,
|
|
9
|
+
stats_reset
|
|
10
|
+
FROM pg_stat_database
|
|
11
|
+
WHERE datname = current_database()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Every index on a user table, with how often it has been scanned since the
|
|
2
|
+
-- statistics were last reset. Constraint indexes are marked so a zero scan
|
|
3
|
+
-- count is not mistaken for waste: they earn their keep on writes.
|
|
4
|
+
SELECT
|
|
5
|
+
s.relname AS table_name,
|
|
6
|
+
s.indexrelname AS index_name,
|
|
7
|
+
s.idx_scan AS scans,
|
|
8
|
+
s.idx_tup_read AS tuples_read,
|
|
9
|
+
pg_relation_size(s.indexrelid) AS size_bytes,
|
|
10
|
+
pg_size_pretty(pg_relation_size(s.indexrelid)) AS size,
|
|
11
|
+
i.indisprimary AS primary_key,
|
|
12
|
+
i.indisunique AS unique_index,
|
|
13
|
+
pg_get_indexdef(s.indexrelid) AS definition
|
|
14
|
+
FROM pg_stat_user_indexes s
|
|
15
|
+
JOIN pg_index i ON i.indexrelid = s.indexrelid
|
|
16
|
+
WHERE s.schemaname = ANY (current_schemas(false))
|
|
17
|
+
ORDER BY pg_relation_size(s.indexrelid) DESC, s.relname, s.indexrelname
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Database cost per controller#action, from SQLcommenter tags.
|
|
2
|
+
--
|
|
3
|
+
-- Catalog queries are excluded throughout: Rails' schema introspection runs
|
|
4
|
+
-- once when a model loads and is tagged with whichever endpoint happened to
|
|
5
|
+
-- trigger it, so it both inflates that endpoint's cost and, sitting at calls=1
|
|
6
|
+
-- forever, destroys the min(calls) request-count estimate below.
|
|
7
|
+
WITH application_queries AS (
|
|
8
|
+
SELECT
|
|
9
|
+
COALESCE(
|
|
10
|
+
substring(query from 'namespaced_controller=''([^'']+)'''),
|
|
11
|
+
substring(query from 'controller=''([^'']+)''')
|
|
12
|
+
) AS controller,
|
|
13
|
+
substring(query from 'action=''([^'']+)''') AS action,
|
|
14
|
+
calls, total_exec_time, rows
|
|
15
|
+
FROM pg_stat_statements
|
|
16
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
17
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
18
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
19
|
+
AND query ~ 'controller=''[^'']+'''
|
|
20
|
+
AND query ~ 'action=''[^'']+'''
|
|
21
|
+
AND query !~* 'pg_catalog|information_schema|pg_index|pg_class|pg_attribute'
|
|
22
|
+
AND query !~* '^\s*SHOW '
|
|
23
|
+
),
|
|
24
|
+
requests AS (
|
|
25
|
+
-- Some query runs exactly once per request, so the smallest call count for an
|
|
26
|
+
-- endpoint approximates how many times it was served.
|
|
27
|
+
SELECT controller, action, min(calls) AS request_count
|
|
28
|
+
FROM application_queries
|
|
29
|
+
GROUP BY controller, action
|
|
30
|
+
)
|
|
31
|
+
SELECT
|
|
32
|
+
q.controller || '#' || q.action AS endpoint,
|
|
33
|
+
SUM(q.total_exec_time) AS total_exec_time_ms,
|
|
34
|
+
SUM(q.calls) AS total_calls,
|
|
35
|
+
COUNT(*) AS query_count,
|
|
36
|
+
SUM(q.rows) AS total_rows,
|
|
37
|
+
r.request_count,
|
|
38
|
+
ROUND((MAX(q.calls)::numeric / NULLIF(r.request_count, 0)), 1) AS max_queries_per_request
|
|
39
|
+
FROM application_queries q
|
|
40
|
+
JOIN requests r ON r.controller = q.controller AND r.action = q.action
|
|
41
|
+
GROUP BY q.controller, q.action, r.request_count
|
|
42
|
+
ORDER BY total_exec_time_ms DESC
|
|
43
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
substring(query from 'job=''([^'']+)''') AS job_class,
|
|
3
|
+
SUM(calls) AS total_calls,
|
|
4
|
+
SUM(total_exec_time) AS total_exec_time_ms,
|
|
5
|
+
COUNT(*) AS query_count
|
|
6
|
+
FROM pg_stat_statements
|
|
7
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
8
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
9
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
10
|
+
AND query ~ 'job=''[^'']+'''
|
|
11
|
+
GROUP BY job_class
|
|
12
|
+
ORDER BY total_exec_time_ms DESC
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
ORDER BY total_exec_time DESC
|
|
13
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
AND query LIKE {{job_pattern}}
|
|
13
|
+
ORDER BY total_exec_time DESC
|
|
14
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Tables whose dead-tuple share is at or above the warning threshold.
|
|
2
|
+
SELECT
|
|
3
|
+
relname,
|
|
4
|
+
n_live_tup,
|
|
5
|
+
n_dead_tup,
|
|
6
|
+
round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_ratio,
|
|
7
|
+
last_autovacuum
|
|
8
|
+
FROM pg_stat_user_tables
|
|
9
|
+
WHERE n_live_tup + n_dead_tup > 0
|
|
10
|
+
AND 100.0 * n_dead_tup / (n_live_tup + n_dead_tup) >= {{threshold}}
|
|
11
|
+
ORDER BY dead_ratio DESC
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
t.relname AS table_name,
|
|
3
|
+
t.seq_scan,
|
|
4
|
+
t.seq_tup_read,
|
|
5
|
+
t.idx_scan,
|
|
6
|
+
t.idx_tup_fetch,
|
|
7
|
+
t.n_tup_ins,
|
|
8
|
+
t.n_tup_upd,
|
|
9
|
+
t.n_tup_del,
|
|
10
|
+
t.n_live_tup,
|
|
11
|
+
t.n_dead_tup,
|
|
12
|
+
t.last_vacuum,
|
|
13
|
+
t.last_autovacuum,
|
|
14
|
+
t.last_analyze,
|
|
15
|
+
t.last_autoanalyze,
|
|
16
|
+
t.vacuum_count,
|
|
17
|
+
t.autovacuum_count,
|
|
18
|
+
t.analyze_count,
|
|
19
|
+
t.autoanalyze_count,
|
|
20
|
+
s.heap_blks_read,
|
|
21
|
+
s.heap_blks_hit,
|
|
22
|
+
s.idx_blks_read,
|
|
23
|
+
s.idx_blks_hit,
|
|
24
|
+
s.toast_blks_read,
|
|
25
|
+
s.toast_blks_hit,
|
|
26
|
+
s.tidx_blks_read,
|
|
27
|
+
s.tidx_blks_hit,
|
|
28
|
+
c.reltuples AS row_estimate
|
|
29
|
+
FROM pg_stat_user_tables t
|
|
30
|
+
LEFT JOIN pg_statio_user_tables s ON t.relid = s.relid
|
|
31
|
+
LEFT JOIN pg_class c ON t.relid = c.oid
|
|
32
|
+
WHERE t.relname = $1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Client sessions on the current database, except the one asking. Every
|
|
2
|
+
-- duration is taken from one clock reading, so they agree with each other;
|
|
3
|
+
-- clock_timestamp() rather than now() because the reader may be inside a
|
|
4
|
+
-- long transaction of its own.
|
|
5
|
+
SELECT
|
|
6
|
+
pid,
|
|
7
|
+
usename,
|
|
8
|
+
application_name,
|
|
9
|
+
client_addr::text AS client_addr,
|
|
10
|
+
state,
|
|
11
|
+
wait_event_type,
|
|
12
|
+
wait_event,
|
|
13
|
+
backend_start,
|
|
14
|
+
xact_start,
|
|
15
|
+
query_start,
|
|
16
|
+
state_change,
|
|
17
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - query_start)))::bigint AS query_ms,
|
|
18
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - xact_start)))::bigint AS xact_ms,
|
|
19
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - state_change)))::bigint AS state_ms,
|
|
20
|
+
array_to_string(pg_blocking_pids(pid), ',') AS blocked_by,
|
|
21
|
+
query
|
|
22
|
+
FROM pg_stat_activity
|
|
23
|
+
WHERE datname = current_database()
|
|
24
|
+
AND backend_type = 'client backend'
|
|
25
|
+
AND pid <> pg_backend_pid()
|
|
26
|
+
ORDER BY pid
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Server-wide connection use. max_connections is a cluster setting, so the
|
|
2
|
+
-- count spans every database. current_user is who pg_peek connects as, for
|
|
3
|
+
-- the hint about hidden query text.
|
|
4
|
+
SELECT
|
|
5
|
+
current_setting('max_connections')::int AS max_connections,
|
|
6
|
+
count(*) FILTER (WHERE backend_type = 'client backend') AS client_connections,
|
|
7
|
+
current_user AS username
|
|
8
|
+
FROM pg_stat_activity
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- What each waiting session is waiting for. A backend waits for at most one
|
|
2
|
+
-- lock at a time, so pid identifies the row. Relations from other databases
|
|
3
|
+
-- render as a bare oid, which the caller filters out by pid anyway.
|
|
4
|
+
SELECT
|
|
5
|
+
pid,
|
|
6
|
+
locktype,
|
|
7
|
+
mode,
|
|
8
|
+
CASE WHEN relation IS NOT NULL THEN relation::regclass::text END AS relation
|
|
9
|
+
FROM pg_locks
|
|
10
|
+
WHERE NOT granted
|
|
11
|
+
AND pid <> pg_backend_pid()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- One row of health figures for the current database.
|
|
2
|
+
SELECT
|
|
3
|
+
round(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 1) AS cache_hit_ratio,
|
|
4
|
+
numbackends AS connections,
|
|
5
|
+
xact_commit,
|
|
6
|
+
xact_rollback,
|
|
7
|
+
deadlocks,
|
|
8
|
+
temp_files,
|
|
9
|
+
stats_reset
|
|
10
|
+
FROM pg_stat_database
|
|
11
|
+
WHERE datname = current_database()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Every index on a user table, with how often it has been scanned since the
|
|
2
|
+
-- statistics were last reset. Constraint indexes are marked so a zero scan
|
|
3
|
+
-- count is not mistaken for waste: they earn their keep on writes.
|
|
4
|
+
SELECT
|
|
5
|
+
s.relname AS table_name,
|
|
6
|
+
s.indexrelname AS index_name,
|
|
7
|
+
s.idx_scan AS scans,
|
|
8
|
+
s.idx_tup_read AS tuples_read,
|
|
9
|
+
pg_relation_size(s.indexrelid) AS size_bytes,
|
|
10
|
+
pg_size_pretty(pg_relation_size(s.indexrelid)) AS size,
|
|
11
|
+
i.indisprimary AS primary_key,
|
|
12
|
+
i.indisunique AS unique_index,
|
|
13
|
+
pg_get_indexdef(s.indexrelid) AS definition
|
|
14
|
+
FROM pg_stat_user_indexes s
|
|
15
|
+
JOIN pg_index i ON i.indexrelid = s.indexrelid
|
|
16
|
+
WHERE s.schemaname = ANY (current_schemas(false))
|
|
17
|
+
ORDER BY pg_relation_size(s.indexrelid) DESC, s.relname, s.indexrelname
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Database cost per controller#action, from SQLcommenter tags.
|
|
2
|
+
--
|
|
3
|
+
-- Catalog queries are excluded throughout: Rails' schema introspection runs
|
|
4
|
+
-- once when a model loads and is tagged with whichever endpoint happened to
|
|
5
|
+
-- trigger it, so it both inflates that endpoint's cost and, sitting at calls=1
|
|
6
|
+
-- forever, destroys the min(calls) request-count estimate below.
|
|
7
|
+
WITH application_queries AS (
|
|
8
|
+
SELECT
|
|
9
|
+
COALESCE(
|
|
10
|
+
substring(query from 'namespaced_controller=''([^'']+)'''),
|
|
11
|
+
substring(query from 'controller=''([^'']+)''')
|
|
12
|
+
) AS controller,
|
|
13
|
+
substring(query from 'action=''([^'']+)''') AS action,
|
|
14
|
+
calls, total_exec_time, rows
|
|
15
|
+
FROM pg_stat_statements
|
|
16
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
17
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
18
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
19
|
+
AND query ~ 'controller=''[^'']+'''
|
|
20
|
+
AND query ~ 'action=''[^'']+'''
|
|
21
|
+
AND query !~* 'pg_catalog|information_schema|pg_index|pg_class|pg_attribute'
|
|
22
|
+
AND query !~* '^\s*SHOW '
|
|
23
|
+
),
|
|
24
|
+
requests AS (
|
|
25
|
+
-- Some query runs exactly once per request, so the smallest call count for an
|
|
26
|
+
-- endpoint approximates how many times it was served.
|
|
27
|
+
SELECT controller, action, min(calls) AS request_count
|
|
28
|
+
FROM application_queries
|
|
29
|
+
GROUP BY controller, action
|
|
30
|
+
)
|
|
31
|
+
SELECT
|
|
32
|
+
q.controller || '#' || q.action AS endpoint,
|
|
33
|
+
SUM(q.total_exec_time) AS total_exec_time_ms,
|
|
34
|
+
SUM(q.calls) AS total_calls,
|
|
35
|
+
COUNT(*) AS query_count,
|
|
36
|
+
SUM(q.rows) AS total_rows,
|
|
37
|
+
r.request_count,
|
|
38
|
+
ROUND((MAX(q.calls)::numeric / NULLIF(r.request_count, 0)), 1) AS max_queries_per_request
|
|
39
|
+
FROM application_queries q
|
|
40
|
+
JOIN requests r ON r.controller = q.controller AND r.action = q.action
|
|
41
|
+
GROUP BY q.controller, q.action, r.request_count
|
|
42
|
+
ORDER BY total_exec_time_ms DESC
|
|
43
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
substring(query from 'job=''([^'']+)''') AS job_class,
|
|
3
|
+
SUM(calls) AS total_calls,
|
|
4
|
+
SUM(total_exec_time) AS total_exec_time_ms,
|
|
5
|
+
COUNT(*) AS query_count
|
|
6
|
+
FROM pg_stat_statements
|
|
7
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
8
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
9
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
10
|
+
AND query ~ 'job=''[^'']+'''
|
|
11
|
+
GROUP BY job_class
|
|
12
|
+
ORDER BY total_exec_time_ms DESC
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
ORDER BY total_exec_time DESC
|
|
13
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
AND query LIKE {{job_pattern}}
|
|
13
|
+
ORDER BY total_exec_time DESC
|
|
14
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- Tables whose dead-tuple share is at or above the warning threshold.
|
|
2
|
+
SELECT
|
|
3
|
+
relname,
|
|
4
|
+
n_live_tup,
|
|
5
|
+
n_dead_tup,
|
|
6
|
+
round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_ratio,
|
|
7
|
+
last_autovacuum
|
|
8
|
+
FROM pg_stat_user_tables
|
|
9
|
+
WHERE n_live_tup + n_dead_tup > 0
|
|
10
|
+
AND 100.0 * n_dead_tup / (n_live_tup + n_dead_tup) >= {{threshold}}
|
|
11
|
+
ORDER BY dead_ratio DESC
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
t.relname AS table_name,
|
|
3
|
+
t.seq_scan,
|
|
4
|
+
t.seq_tup_read,
|
|
5
|
+
t.idx_scan,
|
|
6
|
+
t.idx_tup_fetch,
|
|
7
|
+
t.n_tup_ins,
|
|
8
|
+
t.n_tup_upd,
|
|
9
|
+
t.n_tup_del,
|
|
10
|
+
t.n_live_tup,
|
|
11
|
+
t.n_dead_tup,
|
|
12
|
+
t.last_vacuum,
|
|
13
|
+
t.last_autovacuum,
|
|
14
|
+
t.last_analyze,
|
|
15
|
+
t.last_autoanalyze,
|
|
16
|
+
t.vacuum_count,
|
|
17
|
+
t.autovacuum_count,
|
|
18
|
+
t.analyze_count,
|
|
19
|
+
t.autoanalyze_count,
|
|
20
|
+
s.heap_blks_read,
|
|
21
|
+
s.heap_blks_hit,
|
|
22
|
+
s.idx_blks_read,
|
|
23
|
+
s.idx_blks_hit,
|
|
24
|
+
s.toast_blks_read,
|
|
25
|
+
s.toast_blks_hit,
|
|
26
|
+
s.tidx_blks_read,
|
|
27
|
+
s.tidx_blks_hit,
|
|
28
|
+
c.reltuples AS row_estimate
|
|
29
|
+
FROM pg_stat_user_tables t
|
|
30
|
+
LEFT JOIN pg_statio_user_tables s ON t.relid = s.relid
|
|
31
|
+
LEFT JOIN pg_class c ON t.relid = c.oid
|
|
32
|
+
WHERE t.relname = $1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Client sessions on the current database, except the one asking. Every
|
|
2
|
+
-- duration is taken from one clock reading, so they agree with each other;
|
|
3
|
+
-- clock_timestamp() rather than now() because the reader may be inside a
|
|
4
|
+
-- long transaction of its own.
|
|
5
|
+
SELECT
|
|
6
|
+
pid,
|
|
7
|
+
usename,
|
|
8
|
+
application_name,
|
|
9
|
+
client_addr::text AS client_addr,
|
|
10
|
+
state,
|
|
11
|
+
wait_event_type,
|
|
12
|
+
wait_event,
|
|
13
|
+
backend_start,
|
|
14
|
+
xact_start,
|
|
15
|
+
query_start,
|
|
16
|
+
state_change,
|
|
17
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - query_start)))::bigint AS query_ms,
|
|
18
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - xact_start)))::bigint AS xact_ms,
|
|
19
|
+
round(1000 * EXTRACT(EPOCH FROM (clock_timestamp() - state_change)))::bigint AS state_ms,
|
|
20
|
+
array_to_string(pg_blocking_pids(pid), ',') AS blocked_by,
|
|
21
|
+
query
|
|
22
|
+
FROM pg_stat_activity
|
|
23
|
+
WHERE datname = current_database()
|
|
24
|
+
AND backend_type = 'client backend'
|
|
25
|
+
AND pid <> pg_backend_pid()
|
|
26
|
+
ORDER BY pid
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Server-wide connection use. max_connections is a cluster setting, so the
|
|
2
|
+
-- count spans every database. current_user is who pg_peek connects as, for
|
|
3
|
+
-- the hint about hidden query text.
|
|
4
|
+
SELECT
|
|
5
|
+
current_setting('max_connections')::int AS max_connections,
|
|
6
|
+
count(*) FILTER (WHERE backend_type = 'client backend') AS client_connections,
|
|
7
|
+
current_user AS username
|
|
8
|
+
FROM pg_stat_activity
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- What each waiting session is waiting for. A backend waits for at most one
|
|
2
|
+
-- lock at a time, so pid identifies the row. Relations from other databases
|
|
3
|
+
-- render as a bare oid, which the caller filters out by pid anyway.
|
|
4
|
+
SELECT
|
|
5
|
+
pid,
|
|
6
|
+
locktype,
|
|
7
|
+
mode,
|
|
8
|
+
CASE WHEN relation IS NOT NULL THEN relation::regclass::text END AS relation
|
|
9
|
+
FROM pg_locks
|
|
10
|
+
WHERE NOT granted
|
|
11
|
+
AND pid <> pg_backend_pid()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- One row of health figures for the current database.
|
|
2
|
+
SELECT
|
|
3
|
+
round(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 1) AS cache_hit_ratio,
|
|
4
|
+
numbackends AS connections,
|
|
5
|
+
xact_commit,
|
|
6
|
+
xact_rollback,
|
|
7
|
+
deadlocks,
|
|
8
|
+
temp_files,
|
|
9
|
+
stats_reset
|
|
10
|
+
FROM pg_stat_database
|
|
11
|
+
WHERE datname = current_database()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Every index on a user table, with how often it has been scanned since the
|
|
2
|
+
-- statistics were last reset. Constraint indexes are marked so a zero scan
|
|
3
|
+
-- count is not mistaken for waste: they earn their keep on writes.
|
|
4
|
+
SELECT
|
|
5
|
+
s.relname AS table_name,
|
|
6
|
+
s.indexrelname AS index_name,
|
|
7
|
+
s.idx_scan AS scans,
|
|
8
|
+
s.idx_tup_read AS tuples_read,
|
|
9
|
+
pg_relation_size(s.indexrelid) AS size_bytes,
|
|
10
|
+
pg_size_pretty(pg_relation_size(s.indexrelid)) AS size,
|
|
11
|
+
i.indisprimary AS primary_key,
|
|
12
|
+
i.indisunique AS unique_index,
|
|
13
|
+
pg_get_indexdef(s.indexrelid) AS definition
|
|
14
|
+
FROM pg_stat_user_indexes s
|
|
15
|
+
JOIN pg_index i ON i.indexrelid = s.indexrelid
|
|
16
|
+
WHERE s.schemaname = ANY (current_schemas(false))
|
|
17
|
+
ORDER BY pg_relation_size(s.indexrelid) DESC, s.relname, s.indexrelname
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Database cost per controller#action, from SQLcommenter tags.
|
|
2
|
+
--
|
|
3
|
+
-- Catalog queries are excluded throughout: Rails' schema introspection runs
|
|
4
|
+
-- once when a model loads and is tagged with whichever endpoint happened to
|
|
5
|
+
-- trigger it, so it both inflates that endpoint's cost and, sitting at calls=1
|
|
6
|
+
-- forever, destroys the min(calls) request-count estimate below.
|
|
7
|
+
WITH application_queries AS (
|
|
8
|
+
SELECT
|
|
9
|
+
COALESCE(
|
|
10
|
+
substring(query from 'namespaced_controller=''([^'']+)'''),
|
|
11
|
+
substring(query from 'controller=''([^'']+)''')
|
|
12
|
+
) AS controller,
|
|
13
|
+
substring(query from 'action=''([^'']+)''') AS action,
|
|
14
|
+
calls, total_exec_time, rows
|
|
15
|
+
FROM pg_stat_statements
|
|
16
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
17
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
18
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
19
|
+
AND query ~ 'controller=''[^'']+'''
|
|
20
|
+
AND query ~ 'action=''[^'']+'''
|
|
21
|
+
AND query !~* 'pg_catalog|information_schema|pg_index|pg_class|pg_attribute'
|
|
22
|
+
AND query !~* '^\s*SHOW '
|
|
23
|
+
),
|
|
24
|
+
requests AS (
|
|
25
|
+
-- Some query runs exactly once per request, so the smallest call count for an
|
|
26
|
+
-- endpoint approximates how many times it was served.
|
|
27
|
+
SELECT controller, action, min(calls) AS request_count
|
|
28
|
+
FROM application_queries
|
|
29
|
+
GROUP BY controller, action
|
|
30
|
+
)
|
|
31
|
+
SELECT
|
|
32
|
+
q.controller || '#' || q.action AS endpoint,
|
|
33
|
+
SUM(q.total_exec_time) AS total_exec_time_ms,
|
|
34
|
+
SUM(q.calls) AS total_calls,
|
|
35
|
+
COUNT(*) AS query_count,
|
|
36
|
+
SUM(q.rows) AS total_rows,
|
|
37
|
+
r.request_count,
|
|
38
|
+
ROUND((MAX(q.calls)::numeric / NULLIF(r.request_count, 0)), 1) AS max_queries_per_request
|
|
39
|
+
FROM application_queries q
|
|
40
|
+
JOIN requests r ON r.controller = q.controller AND r.action = q.action
|
|
41
|
+
GROUP BY q.controller, q.action, r.request_count
|
|
42
|
+
ORDER BY total_exec_time_ms DESC
|
|
43
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
substring(query from 'job=''([^'']+)''') AS job_class,
|
|
3
|
+
SUM(calls) AS total_calls,
|
|
4
|
+
SUM(total_exec_time) AS total_exec_time_ms,
|
|
5
|
+
COUNT(*) AS query_count
|
|
6
|
+
FROM pg_stat_statements
|
|
7
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
8
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
9
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
10
|
+
AND query ~ 'job=''[^'']+'''
|
|
11
|
+
GROUP BY job_class
|
|
12
|
+
ORDER BY total_exec_time_ms DESC
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
ORDER BY total_exec_time DESC
|
|
13
|
+
LIMIT {{limit}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
SELECT
|
|
2
|
+
interval '1 millisecond' * total_exec_time AS total_exec_time,
|
|
3
|
+
COALESCE(to_char((total_exec_time/NULLIF(sum(total_exec_time) OVER(), 0)) * 100, 'FM990D0'), '0') || '%' AS prop_exec_time,
|
|
4
|
+
to_char(calls, 'FM999G999G999G990') AS ncalls,
|
|
5
|
+
ROUND(total_exec_time/NULLIF(calls, 0)) AS avg_exec_ms,
|
|
6
|
+
interval '1 millisecond' * (shared_blk_read_time + shared_blk_write_time) AS sync_io_time,
|
|
7
|
+
query
|
|
8
|
+
FROM pg_stat_statements
|
|
9
|
+
WHERE userid = (SELECT usesysid FROM pg_user WHERE usename = current_user LIMIT 1)
|
|
10
|
+
AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
|
|
11
|
+
AND query NOT LIKE '%/* pg_peek */%'
|
|
12
|
+
AND query LIKE {{job_pattern}}
|
|
13
|
+
ORDER BY total_exec_time DESC
|
|
14
|
+
LIMIT {{limit}}
|