SiamCafe · Blog
PostgreSQL Performance Tuning Production
บทความ

PostgreSQL Performance Tuning Production

เผยแพร่ 28 พฤษภาคม 2569

PostgreSQL Performance Tuning คืออะไร?

PostgreSQL เป็น database ที่ทรงพลังที่สุดในโลก open-source แต่ default config ถูกตั้งมาให้ทำงานบนเครื่องที่มี RAM แค่ 1-2 GB ดังนั้น ถ้าใช้ PostgreSQL ใน production โดยไม่ tune ก็เหมือนขับ Ferrari ด้วยเกียร์ 1 ตลอดทาง

บทความนี้จะสอนวิธี tune PostgreSQL ให้เร็วขึ้น 5-20 เท่าสำหรับ server ที่มี RAM 16 GB ขึ้นไป

postgresql.conf — ค่าสำคัญที่ต้อง Tune

ParameterDefaultแนะนำ (RAM 32GB)คำอธิบาย
shared_buffers128 MB8 GB (25% RAM)Buffer pool สำหรับ cache data pages
effective_cache_size4 GB24 GB (75% RAM)บอก planner ว่ามี cache เท่าไหร่
work_mem4 MB64-256 MBMemory per sort/hash operation
maintenance_work_mem64 MB2 GBMemory สำหรับ VACUUM, CREATE INDEX
max_connections100200ใช้ PgBouncer แทนการเพิ่ม
wal_buffers-164 MBBuffer สำหรับ WAL writes
random_page_cost4.01.1ลดลงถ้าใช้ SSD (สำคัญมาก!)
effective_io_concurrency1200เพิ่มสำหรับ SSD/NVMe

ตัวอย่าง Config สำหรับ Server RAM 32 GB

# /etc/postgresql/16/main/postgresql.conf

# Memory
shared_buffers = '8GB'
effective_cache_size = '24GB'
work_mem = '128MB'
maintenance_work_mem = '2GB'
wal_buffers = '64MB'

# Disk / SSD optimization
random_page_cost = 1.1
effective_io_concurrency = 200
max_parallel_workers_per_gather = 4
max_parallel_workers = 8

# WAL / Checkpoints
wal_level = replica
max_wal_size = '4GB'
min_wal_size = '1GB'
checkpoint_completion_target = 0.9

# Connections (ใช้ PgBouncer แทน)
max_connections = 200

# Logging
log_min_duration_statement = 500 # log queries ที่นานกว่า 500ms
log_checkpoints = on
log_lock_waits = on

Index Optimization — หัวใจของ Performance

Index ที่ดีทำให้ query เร็วขึ้น 100-1000 เท่าข้อแนะนำ:

  • ดู slow queries ก่อน — เปิด pg_stat_statements extension แล้วดู query ที่ช้าที่สุด
  • ใช้ EXPLAIN ANALYZEEXPLAIN (ANALYZE, BUFFERS) SELECT ... ดูว่า query ใช้ Seq Scan หรือ Index Scan
  • สร้าง Partial IndexCREATE INDEX ON orders (status) WHERE status = 'pending' ถ้า query filter ค่าเดิมซ้ำๆ
  • ใช้ Covering IndexCREATE INDEX ON users (email) INCLUDE (name, role) ลด table lookup
  • หา Missing Indexes — ดูจาก pg_stat_user_tables ถ้า seq_scan สูงมากแสดงว่าขาด index

Connection Pooling ด้วย PgBouncer

PostgreSQL สร้าง process ใหม่ทุก connection ใช้ RAM ~10 MB ต่อ connection ถ้ามี 500 connections = 5 GB RAM เฉพาะ connections PgBouncer แก้ปัญหานี้โดย pool connections ให้ reuse

# /etc/pgbouncer/pgbouncer.ini
[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
pool_mode = transaction # แนะนำ transaction mode
max_client_conn = 1000
default_pool_size = 50
min_pool_size = 10

ผลลัพธ์: app เชื่อมต่อ PgBouncer port 6432 แทน PostgreSQL port 5432 โดย PgBouncer จะ pool 1000 client connections ผ่าน 50 PostgreSQL connections จริงลด memory usage ได้มหาศาล

VACUUM และ Maintenance

PostgreSQL ใช้ MVCC ที่สร้าง dead tuples ทุกครั้งที่ UPDATE/DELETE ถ้าไม่ VACUUM ตารางจะบวมขึ้นเรื่อยๆ:

  • autovacuum — เปิดเสมอ (default on) อย่าปิด
  • ตั้ง autovacuum ให้ aggressive ขึ้น สำหรับตารางที่ update บ่อย
  • pg_repack — ใช้ repack table ที่บวมมากโดยไม่ต้อง lock table
  • ตรวจสอบ bloatSELECT relname, n_dead_tup FROM pg_stat_user_tables ORDER BY n_dead_tup DESC;

Q: PostgreSQL vs MySQL ใน production ตัวไหนดีกว่า?

ขึ้นอยู่กับ use case ครับ PostgreSQL ดีกว่าสำหรับ complex queries, JSON, geospatial, full-text search และ data integrity MySQL ดีกว่าสำหรับ simple read-heavy workloads และ replication ง่ายกว่าในปี 2026 PostgreSQL ได้รับความนิยมมากกว่าแล้ว