| tags |
name |
description |
triggers |
version |
|
|
postgres |
PostgreSQL operations — SQL queries, pg_dump/restore, performance tuning, user management, and common troubleshooting. |
| postgres |
| postgresql |
| pg_dump |
| psql |
| pg_restore |
| 数据库 |
|
1.0.0 |
PostgreSQL
Connect
# Local
psql -d mydb
psql -d mydb -U postgres
# Remote
psql -h 192.168.1.10 -p 5432 -d mydb -U postgres
# With URI
psql postgresql://postgres:secret@localhost:5432/mydb
Common Queries
-- List databases
SELECT datname FROM pg_database WHERE datistpl = false;
-- List tables
SELECT tablename FROM pg_tables WHERE schemaname = 'public';
-- List columns
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'my_table';
-- Describe table
\d my_table
\d+ my_table
-- Row count
SELECT COUNT(*) FROM my_table;
-- Sample rows
SELECT * FROM my_table LIMIT 10;
-- Find rows by condition
SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- Aggregate
SELECT category, COUNT(*) as count, AVG(price) as avg_price
FROM products GROUP BY category HAVING COUNT(*) > 5;
CRUD
-- Insert
INSERT INTO users (name, email, created_at)
VALUES ('Alice', 'alice@example.com', NOW());
-- Multi-row insert
INSERT INTO users (name, email) VALUES
('Bob', 'bob@example.com'),
('Carol', 'carol@example.com');
-- Update
UPDATE users SET email = 'new@example.com' WHERE id = 42;
-- Delete
DELETE FROM users WHERE id = 42;
-- Upsert (insert or update on conflict)
INSERT INTO users (id, name, email) VALUES (1, 'Alice', 'alice@example.com')
ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email;
Index
-- Create index
CREATE INDEX idx_users_email ON users(email);
-- Unique index
CREATE UNIQUE INDEX idx_users_email ON users(email);
-- Composite index
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at DESC);
-- Partial index
CREATE INDEX idx_active_users ON users(email) WHERE active = true;
-- Check index usage
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
Schema
-- Create table
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10,2) DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
-- Add column
ALTER TABLE products ADD COLUMN category VARCHAR(100);
-- Rename column
ALTER TABLE products RENAME COLUMN price TO unit_price;
-- Drop column
ALTER TABLE products DROP COLUMN IF EXISTS old_col;
-- Add constraint
ALTER TABLE products ADD CONSTRAINT positive_price CHECK (price >= 0);
User / Role Management
-- Create user
CREATE USER alice WITH PASSWORD 'secret_password';
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE mydb TO alice;
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO alice;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO alice;
-- Revoke
REVOKE ALL ON mydb FROM alice;
-- Change password
ALTER USER alice WITH PASSWORD 'new_password';
-- Drop user
DROP USER IF EXISTS alice;
Backup / Restore
# Dump (SQL file)
pg_dump -d mydb -U postgres -f backup.sql
pg_dump -d mydb -U postgres -Fc -f backup.dump # custom format (compressed)
# Dump all databases
pg_dumpall -U postgres -f all_databases.sql
# Dump specific tables
pg_dump -d mydb -U postgres -t orders -t products > tables.sql
# Restore
psql -d mydb -U postgres -f backup.sql
pg_restore -d mydb -U postgres backup.dump # custom format
# Restore to new database
createdb newdb
pg_restore -d newdb -U postgres backup.dump
Service Management
# Debian/Ubuntu (systemd)
sudo systemctl start postgresql
sudo systemctl stop postgresql
sudo systemctl restart postgresql
sudo systemctl status postgresql
# Debian/Ubuntu cluster
sudo -u postgres pg_ctlcluster 16 main status
sudo -u postgres pg_ctlcluster 16 main restart
# RHEL/CentOS
sudo systemctl start postgresql-16
sudo systemctl status postgresql-16
Common Maintenance
-- Analyze table (update query planner stats)
ANALYZE users;
-- Vacuum (reclaim space, remove dead rows)
VACUUM users;
VACUUM FULL users; -- requires exclusive lock, use carefully on live DB
-- Check table size
SELECT pg_size_pretty(pg_total_relation_size('users'));
SELECT pg_size_pretty(pg_relation_size('users'));
-- Check index size
SELECT pg_size_pretty(pg_indexes_size('users'));
-- Find unused indexes
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0;
-- Long-running queries
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state != 'idle' AND application_name != 'psql'
ORDER BY duration DESC;
Kill Long Queries
-- Cancel gracefully
SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE ...;
-- Hard kill (last resort)
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE ...;
Performance Tuning
-- Enable measuring query planning/execution time
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ...
Key settings to check in postgresql.conf:
shared_buffers — typically 25% of RAM
effective_cache_size — typically 75% of RAM
work_mem — per-sort memory, increase for large sorts
maintenance_work_mem — for VACUUM, CREATE INDEX
max_connections — cap at ~100 for most setups
Useful psql Commands
\h -- SQL help
\h INSERT -- help on specific command
\du -- list users/roles
\d -- list tables
\di -- list indexes
\ds -- list sequences
\dv -- list views
\l -- list databases
\c mydb -- connect to database
\dt -- list tables in current schema
\x -- toggle expanded display (wide tables)
\i file.sql -- execute SQL file
\copy -- copy data to/from file
\q -- quit
Docker
# Run postgres container
docker run -d --name postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=mydb \
-v postgres_data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
# Connect from host
psql -h localhost -p 5432 -U postgres -d mydb
Troubleshooting
| Problem |
Fix |
connection refused |
Check pg_hba.conf allows connection, verify port 5432 is open |
password authentication failed |
Check pg_hba.conf method, reset password or fix connection string |
too many clients |
Increase max_connections or use connection pooler (pgbouncer) |
| Slow queries |
EXPLAIN ANALYZE, add indexes, increase work_mem |
| Disk full |
VACUUM FULL, delete old WAL archives, pg_dump + pg_restore to new disk |
| Cannot start after crash |
Check pg_wal/ integrity, try pg_resetwal, check disk space |