SELECT
pid,
age(query_start, clock_timestamp()),
usename,
query
FROM pg_stat_activity
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%'
ORDER BY query_start desc;SELECT pid,
usename AS login,
application_name AS app,
to_char(xact_start, 'HH24:MI:SS') AS tx_start,
date_trunc('second', (now() - xact_start)) AS tx_duration,
to_char(query_start, 'HH24:MI:SS') AS query_start,
date_trunc('second', (now() - query_start)) AS query_duration,
wait_event_type || '/' || wait_event AS waiting,
state,
left(REPLACE(query, E'\n', ' '), 200) AS query
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY query_start
LIMIT 30;SELECT
pid, -- pg_terminate_backend(pid),
usename as login,
application_name as app,
to_char(xact_start, 'HH24:MI:SS') AS tx_start,
date_trunc('second', (now() - xact_start)) AS tx_duration,
to_char(query_start, 'HH24:MI:SS') AS query_start,
date_trunc('second', (now() - query_start)) AS query_duration,
wait_event_type || '/' || wait_event as waiting,
state,
left(REPLACE(query, E'\n', ' '), 200) as query
FROM pg_stat_activity
WHERE state != 'idle' and application_name LIKE 'NAME%'
ORDER BY query_start
LIMIT 30;SELECT schemaname, tblname, to_char((((tblpages-est_tblpages_ff)*bs)/(1024::NUMERIC^2))::INT, '9G999G999G999') AS bloat_mb,
CASE
WHEN tblpages = 0 THEN 0
WHEN tblpages - est_tblpages_ff > 0
THEN round((100 * (tblpages - est_tblpages_ff)/tblpages::float)::NUMERIC,2)
ELSE 0
END AS bloat_ratio
FROM (
SELECT
ceil( reltuples / ( (bs-page_hdr)/tpl_size ) ) + ceil( toasttuples / 4 ) AS est_tblpages,
ceil( reltuples / ( (bs-page_hdr)*fillfactor/(tpl_size*100) ) ) + ceil( toasttuples / 4 ) AS est_tblpages_ff,
tblpages, fillfactor, bs, schemaname, tblname, heappages, toastpages
FROM (
SELECT
( 4 + tpl_hdr_size + tpl_data_size + (2*ma)
- CASE WHEN ceil(tpl_data_size)::int%ma = 0 THEN ma ELSE ceil(tpl_data_size)::int%ma END
) AS tpl_size, (heappages + toastpages) AS tblpages, heappages,
toastpages, reltuples, toasttuples, bs, page_hdr, schemaname, tblname, fillfactor
FROM (
SELECT
ns.nspname AS schemaname, tbl.relname AS tblname, tbl.reltuples,
tbl.relpages AS heappages, coalesce(toast.relpages, 0) AS toastpages,
coalesce(toast.reltuples, 0) AS toasttuples,
coalesce(substring(
array_to_string(tbl.reloptions, ' ')
FROM '%fillfactor=#"__#"%' FOR '#')::smallint, 100) AS fillfactor,
current_setting('block_size')::numeric AS bs,
CASE WHEN version()~'mingw32' OR version()~'64-bit|x86_64|ppc64|ia64|amd64' THEN 8 ELSE 4 END AS ma,
24 AS page_hdr,
23 + CASE WHEN MAX(coalesce(null_frac,0)) > 0 THEN ( 7 + count(*) ) / 8 ELSE 0::int END AS tpl_hdr_size,
sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024) ) AS tpl_data_size
FROM pg_attribute AS att
JOIN pg_class AS tbl ON att.attrelid = tbl.oid
JOIN pg_namespace AS ns ON ns.oid = tbl.relnamespace
LEFT JOIN pg_stats AS s ON s.schemaname=ns.nspname
AND s.tablename = tbl.relname AND s.inherited=false AND s.attname=att.attname
LEFT JOIN pg_class AS toast ON tbl.reltoastrelid = toast.oid
WHERE att.attnum > 0 AND NOT att.attisdropped
AND tbl.relkind = 'r'
GROUP BY 1,2,3,4,5,6,7,8,9
ORDER BY 2
) AS s
) AS s2
) AS s3
ORDER BY ((tblpages-est_tblpages_ff)*bs) desc,bloat_ratio desc
LIMIT 30;WITH btree_index_atts AS (
SELECT nspname,
indexclass.relname as index_name,
indexclass.reltuples,
indexclass.relpages,
indrelid, indexrelid,
indexclass.relam,
tableclass.relname as tablename,
regexp_split_to_table(indkey::text, ' ')::smallint AS attnum,
indexrelid as index_oid
FROM pg_index
JOIN pg_class AS indexclass ON pg_index.indexrelid = indexclass.oid
JOIN pg_class AS tableclass ON pg_index.indrelid = tableclass.oid
JOIN pg_namespace ON pg_namespace.oid = indexclass.relnamespace
JOIN pg_am ON indexclass.relam = pg_am.oid
WHERE pg_am.amname = 'btree' AND indexclass.relpages > 0
AND nspname NOT IN ('pg_catalog','information_schema')
),
index_item_sizes AS (
SELECT
ind_atts.nspname, ind_atts.index_name,
ind_atts.reltuples, ind_atts.relpages, ind_atts.relam,
indrelid AS table_oid, index_oid,
current_setting('block_size')::numeric AS bs,
8 AS maxalign,
24 AS pagehdr,
CASE WHEN max(coalesce(pg_stats.null_frac,0)) = 0
THEN 2
ELSE 6
END AS index_tuple_hdr,
sum( (1-coalesce(pg_stats.null_frac, 0)) * coalesce(pg_stats.avg_width, 1024) ) AS nulldatawidth
FROM pg_attribute
JOIN btree_index_atts AS ind_atts ON pg_attribute.attrelid = ind_atts.indexrelid AND pg_attribute.attnum = ind_atts.attnum
JOIN pg_stats ON pg_stats.schemaname = ind_atts.nspname
-- stats for regular index columns
AND ( (pg_stats.tablename = ind_atts.tablename AND pg_stats.attname = pg_catalog.pg_get_indexdef(pg_attribute.attrelid, pg_attribute.attnum, TRUE))
-- stats for functional indexes
OR (pg_stats.tablename = ind_atts.index_name AND pg_stats.attname = pg_attribute.attname))
WHERE pg_attribute.attnum > 0
GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
),
index_aligned_est AS (
SELECT maxalign, bs, nspname, index_name, reltuples,
relpages, relam, table_oid, index_oid,
coalesce (
ceil (
reltuples * ( 6
+ maxalign
- CASE
WHEN index_tuple_hdr%maxalign = 0 THEN maxalign
ELSE index_tuple_hdr%maxalign
END
+ nulldatawidth
+ maxalign
- CASE /* Add padding to the data to align ON MAXALIGN */
WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
ELSE nulldatawidth::integer%maxalign
END
)::numeric
/ ( bs - pagehdr::NUMERIC )
+1 )
, 0 )
as expected
FROM index_item_sizes
),
raw_bloat AS (
SELECT current_database() as dbname, nspname, pg_class.relname AS table_name, index_name,
bs*(index_aligned_est.relpages)::bigint AS totalbytes, expected,
CASE
WHEN index_aligned_est.relpages <= expected
THEN 0
ELSE bs*(index_aligned_est.relpages-expected)::bigint
END AS wastedbytes,
CASE
WHEN index_aligned_est.relpages <= expected
THEN 0
ELSE bs*(index_aligned_est.relpages-expected)::bigint * 100 / (bs*(index_aligned_est.relpages)::bigint)
END AS realbloat,
pg_relation_size(index_aligned_est.table_oid) as table_bytes,
stat.idx_scan as index_scans
FROM index_aligned_est
JOIN pg_class ON pg_class.oid=index_aligned_est.table_oid
JOIN pg_stat_user_indexes AS stat ON index_aligned_est.index_oid = stat.indexrelid
),
format_bloat AS (
SELECT nspname || '.' || table_name as table_name,
nspname || '.' || index_name as index_name,
round(realbloat) as bloat_pct,
round(wastedbytes/(1024^2)::BIGINT) as bloat_mb,
(totalbytes/(1024^2))::BIGINT as index_mb,
(table_bytes/(1024^2))::BIGINT as table_mb,
(index_scans/1000)::BIGINT as K_index_scans
FROM raw_bloat
)
-- final query outputting the bloated indexes
-- change the where AND order by to change
-- what shows up as bloated
SELECT *
FROM format_bloat
WHERE bloat_mb >= 100
AND bloat_pct >= 70
ORDER BY bloat_mb DESC;SELECT
schemaname,
relname,
last_vacuum,
last_autovacuum,
last_analyze,
last_autoanalyze
FROM pg_stat_user_tables
WHERE relname = 'NAME';SELECT
clock_timestamp(),
pg_class.relname,
pg_locks.locktype,
pg_locks.database,
pg_locks.relation,
pg_locks.page,
pg_locks.tuple,
pg_locks.virtualtransaction,
pg_locks.pid,
pg_locks.mode,
pg_locks.granted
FROM pg_locks
JOIN pg_class ON pg_locks.relation = pg_class.oid
WHERE relname !~ '^pg_' AND relname <> 'active_locks';SELECT
c.oid,
nspname AS table_schema,
relname AS TABLE_NAME,
c.reltuples AS row_estimate,
pg_size_pretty(pg_total_relation_size(c.oid)) AS total_bytes,
pg_size_pretty(pg_indexes_size(c.oid)) AS index_bytes,
pg_size_pretty(pg_total_relation_size(reltoastrelid)) AS toast_bytes
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE relkind = 'r' AND relname = 'TABLE_NAME';SELECT
schemaname AS "Schema",
relname AS "Table",
pg_size_pretty(pg_total_relation_size(relid)) AS "Size",
pg_size_pretty(pg_total_relation_size(relid) - pg_relation_size(relid)) AS "External Size"
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;SELECT *
FROM pg_stat_activity
WHERE datname = 'NAME' SELECT
ctid, -- physical location
xmin, -- insertion transaction
xmax, -- deletion transaction
*
FROM <table>;SELECT now() - xact_start AS duration,
pid,
query_start,
application_name,
left(REPLACE(query, E'\n', ''), 2000)
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY 1 DESC, 3 ASC
LIMIT 10;SELECT indexrelname,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_user_indexes
WHERE schemaname = 'SCHEMA' and relname = 'TABLE_NAME';SELECT
blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS current_statement_in_blocking_process
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.database IS NOT DISTINCT FROM blocked_locks.database
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;WITH fk_list AS (
SELECT pg_constraint.oid AS fkoid, conrelid, confrelid AS parentid,
conname, relname, nspname,confupdtype,confdeltype,
conkey AS key_cols
FROM pg_constraint
JOIN pg_class ON conrelid = pg_class.oid
JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
WHERE contype = 'f'
),
fk_attributes AS (
SELECT fkoid, conrelid, attname, attnum
FROM fk_list
JOIN pg_attribute
ON conrelid = attrelid
AND attnum = ANY( key_cols )
ORDER BY fkoid, attnum
),
fk_cols_list AS (
SELECT fkoid, array_agg(attname) AS cols_list
FROM fk_attributes
GROUP BY fkoid
),
index_list AS (
SELECT indexrelid AS indexid,
pg_class.relname AS indexname,
indrelid,
indkey,
indpred IS NOT NULL AS has_predicate,
pg_get_indexdef(indexrelid) AS indexdef
FROM pg_index
JOIN pg_class ON indexrelid = pg_class.oid
WHERE indisvalid
),
fk_index_match AS (
SELECT fk_list.*,
indexid,
indexname,
indkey::int[] AS indexatts,
has_predicate,
indexdef,
array_length(key_cols, 1) AS fk_colcount,
array_length(indkey,1) AS index_colcount,
cols_list
FROM fk_list
JOIN fk_cols_list USING (fkoid)
LEFT OUTER JOIN index_list
ON conrelid = indrelid
AND (indkey::int2[])[0:(array_length(key_cols,1) -1)] @> key_cols
)
,fk_perfect_match AS (
SELECT fkoid, has_predicate
FROM fk_index_match
WHERE NOT has_predicate
AND indexdef LIKE '%USING btree%'
)
,fk_index_check AS (
SELECT 'MISSING_INDEX' AS issue, *, 1 AS issue_sort
FROM fk_index_match
WHERE indexid IS NULL
UNION ALL
SELECT 'PARTIAL_INDEX' AS issue, *, 2 AS issue_sort
FROM fk_index_match
WHERE indexid IS NOT NULL
AND fkoid NOT IN (
SELECT fkoid
FROM fk_perfect_match)
)
SELECT nspname AS schema_name,
relname AS table_name,
conname AS fk_name,
cols_list AS fk_columns,
issue AS issue_type
FROM fk_index_check
ORDER BY issue_sort, table_name, fk_name;SET client_encoding TO 'UTF8';
\COPY (SELECT * FROM <TABLE_NAME> ) to 'export.csv' WITH CSV HEADER DELIMITER ';'
-- remove template flag to allow deletion
ALTER database template1 is_template=false;
DROP database template1;
-- define your own custom config
CREATE DATABASE template1
WITH OWNER = postgres
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'en_US.UTF-8'
LC_CTYPE = 'en_US.UTF-8'
CONNECTION LIMIT = -1
TEMPLATE template0;
-- define database as template
ALTER database template1 is_template=true;add in $HOME/.psqlrc
\timing on
\pset linestyle unicode
\pset border 2
\setenv PAGER 'pspg --no-mouse -bX --no-commandbar --no-topbar'
\set HISTSIZE 100000log_min_duration_statement = 0
log_line_prefix = '%t [%p]: [%l-1] '
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0
log_error_verbosity = default
log_statement = 'none'
# if psql is not in english
# lc_messages='C'
track_activity_query_size = 16384
echo "" > /usr/local/var/log/postgres.logRun pgbadger, more information see : https://github.com/dalibo/pgbadger
pgbadger /path/to/my/postgres-log-file.logcp psqlrc $HOME/.psqlrccp psqlrc.menu $HOME/.psqlrc.menu