Skip to content

Postgres

IAM

Create user

sql
CREATE DATABASE $DATABASE;
CREATE USER $USER WITH ENCRYPTED PASSWORD '$PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE mydb TO $USER;

Create role

sql
CREATE ROLE $ROLE WITH LOGIN PASSWORD '$PASSWORD';

Grant permissions

sql
-- admin
GRANT SELECT, INSERT, UPDATE, DELETE ON all tables IN SCHEMA public TO {ROLE};

-- readonly
GRANT SELECT ON all tables IN SCHEMA public TO {ROLE};

-- readonly-specific schema
GRANT SELECT ON {SCHEMA} TO {ROLE};

-- allow execute functions
GRANT EXECUTE ON all functions IN SCHEMA public TO user;

Activity

Get activity log

sql
SELECT usename,datname,count(*)
FROM pg_stat_activity
GROUP BY usename,datname;

with runtime

sql
SELECT pid, datname, usename, query_start, now() - query_start as runtime, query
FROM pg_stat_activity
ORDER BY runtime;

Get session count

sql
SELECT count(*)
FROM pg_stat_activity;

Vacuum

sql
-- full stats
SELECT relname, seq_scan, n_live_tup, n_dead_tup, n_tup_del, last_autovacuum, last_autoanalyze, autovacuum_count, autovacuum_count FROM pg_stat_user_tables;

-- see alive/dead row count
SELECT n_live_tup, n_dead_tup, relname FROM pg_stat_all_tables;

-- prune dead rows
VACUUM job_ticks;

See indexing progress

sql
SELECT
   p.phase,
   p.blocks_total,
   p.blocks_done,
        p.blocks_total - p.blocks_done as blocks_left,
   p.tuples_total,
   p.tuples_done,
   ai.schemaname,
   ai.relname,
   ai.indexrelname
FROM pg_stat_progress_create_index p
JOIN pg_stat_activity a ON p.pid = a.pid
LEFT JOIN pg_stat_all_indexes ai on ai.relid = p.relid AND ai.indexrelid = p.index_relid;

Terminate process

sql
SELECT * FROM pg_stat_activity;
SELECT pg_terminate_backend(${PID});

Statistics

Find most used tables

sql
SELECT schemaname, relname,
       COALESCE(seq_scan, 0) + COALESCE(idx_scan, 0) nr_accesses
FROM pg_stat_all_tables
WHERE schemaname='public'
ORDER BY 3 DESC NULLS LAST;

Get table size

sql
SELECT
    table_name,
    pg_relation_size(quote_ident(table_name)),
    pg_size_pretty(pg_relation_size(quote_ident(table_name)))
FROM
    information_schema.tables
WHERE
    table_schema = 'public'
ORDER BY
    pg_total_relation_size(quote_ident(table_name)) DESC;

Get index size

sql
SELECT
   relname  as table_name,
   pg_size_pretty(pg_total_relation_size(relid)) As "Total Size",
   pg_size_pretty(pg_indexes_size(relid)) as "Index Size",
   pg_size_pretty(pg_relation_size(relid)) as "Actual Size"
   FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;

Collation

bash
CREATE DATABASE $your_database_name LC_COLLATE='th_TH.utf8' LC_CTYPE='th_TH.utf8' TEMPLATE=template0;

Backup and restore

bash
# backup
$ pg_dump --host HOST --port 5432 --username USERNAME --format plain --verbose --file OUTFILE.sql --table public.TABLE_NAME DB_NAME
$ psql --host HOST --port 5432 --username USERNAME -d DB_NAME < BACKUP.sql

## another variant
# compression rate: 10x
$ pg_dump --host $HOST --port $PORT --username $USERNAME --dbname $DBNAME -t $TABLE_NAME -Fc -f $FILENAME.bin
$ pg_restore --host $HOST --port $PORT --username $USERNAME --dbname $DBNAME --no-owner --no-privileges  $FILENAME.bin

PSQL

bash
# list databases
\l

# list tables
\dt

# list column dtypes
\d+ table_name

# list indexes and size
\di+ {INDEX_PREFIX}*

# select database
\c {DB_NAME}

# login
psql -h HOST -d DB_NAME -U USER

# export to csv
db> \copy (SELECT  * FROM district_boundary) TO '~/Downloads/file.tsv' WITH (FORMAT CSV, HEADER, DELIMITER E'\t')

# export stdout to file
db> \o out.txt

Troubleshooting

Tools

Playground

Resources