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
- Supabase WASM - PostgreSQL in the Browser