คู่มือ Tuning PostgreSQL บน DigitalOcean Droplet 2026
A practical guide to tuning self-hosted PostgreSQL on a DigitalOcean Droplet, from core memory parameters to knowing when to switch to a managed database.
PostgreSQL ที่ติดตั้งบน Droplet ด้วยค่าเริ่มต้นจากแพ็กเกจ apt มักไม่ได้ถูกปรับแต่งให้เหมาะกับสเปกเครื่องจริง เพราะค่า default ของ PostgreSQL ถูกออกแบบมาให้รันได้บนเครื่องแรมน้อยที่สุด ไม่ใช่ Droplet ที่มี RAM 2GB, 4GB หรือมากกว่านั้น บทความนี้อธิบายขั้นตอนติดตั้งและปรับค่าพารามิเตอร์หลักของ PostgreSQL บน Droplet แบบมีตัวอย่างคำสั่งจริง รวมถึงจังหวะที่ควรเลิกดูแลเองแล้วย้ายไปใช้ Managed Database แทน
สารบัญ
- ติดตั้ง PostgreSQL บน Droplet
- ค่าพื้นฐานที่ควรปรับ: shared_buffers, work_mem
- Index และ Query Performance เบื้องต้น
- เมื่อไหร่ควรย้ายไปใช้ Managed Database
- Backup ด้วย pg_dump และ Volume Snapshot
- เมื่อไหร่ควรใช้ฟีเจอร์นี้ (Use Case จริง)
- ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
- แนวทางปฏิบัติที่ดีที่สุด (Best Practices)
- FAQ
ติดตั้ง PostgreSQL บน Droplet
การติดตั้ง PostgreSQL บน Droplet ที่รัน Ubuntu หรือ Debian ทำได้ผ่าน apt โดยตรง เริ่มจากอัปเดต package list ด้วย sudo apt update แล้วติดตั้งด้วย sudo apt install postgresql postgresql-contrib ระบบจะติดตั้งทั้งตัวเซิร์ฟเวอร์ postgresql และส่วนขยาย contrib ที่มี extension มาตรฐานอย่าง pg_stat_statements ติดมาด้วย หลังติดตั้งเสร็จ service จะสตาร์ทอัตโนมัติ ตรวจสอบสถานะได้ด้วย sudo systemctl status postgresql
ขั้นตอนถัดไปคือตั้งรหัสผ่านให้ user ระบบ postgres ด้วยการเข้าไปที่ psql shell ก่อน: sudo -u postgres psql แล้วรันคำสั่ง ALTER USER postgres WITH PASSWORD 'ตั้งรหัสผ่านที่นี่'; ภายใน shell จากนั้นออกด้วย \q ไฟล์ configuration หลักสองไฟล์ที่ต้องรู้จักคือ postgresql.conf ซึ่งควบคุมค่าพารามิเตอร์การทำงานของ instance ทั้งหมด และ pg_hba.conf ซึ่งควบคุมว่า client จากไหนเชื่อมต่อได้บ้างและด้วย authentication method ใด ทั้งสองไฟล์อยู่ที่ /etc/postgresql/16/main/ บน Ubuntu 24.04 (เลขเวอร์ชันในพาธจะเปลี่ยนตาม major version ที่ apt ติดตั้งให้)
สำหรับ Droplet ที่จะใช้รัน PostgreSQL จริงจัง ควรเลือกสเปกที่มี RAM อย่างน้อย 2GB ขึ้นไป เพราะ PostgreSQL ต้องใช้หน่วยความจำสำหรับ shared buffer, connection แต่ละตัว และ work memory ของ query ที่ซับซ้อน Droplet ขนาดเล็กสุดที่ 512MiB RAM เหมาะกับการทดลองหรือ งานเรียนรู้เท่านั้น หากเปิดให้ client ภายนอกเชื่อมต่อ ต้องแก้ listen_addresses = '*' ใน postgresql.conf และเพิ่มบรรทัด อนุญาต IP ใน pg_hba.conf ร่วมกับเปิด Cloud Firewall เฉพาะพอร์ต 5432 จาก IP ที่ไว้ใจได้เท่านั้น ห้ามเปิดพอร์ต 5432 ออกสู่อินเทอร์เน็ตแบบ ไม่จำกัด IP โดยเด็ดขาด เพราะเป็นช่องโหว่ที่ scanner อัตโนมัติค้นหาอยู่ตลอดเวลา
Installing PostgreSQL on a Droplet running Ubuntu or Debian can be done directly via apt. Start by updating the package list with sudo apt update and then install with sudo apt install postgresql postgresql-contrib. The system will install both the postgresql server and the contrib extensions which come with standard extensions like pg_stat_statements. After installation completes, the service starts automatically. You can check the status with sudo systemctl status postgresql.
The next step is to set a password for the postgres system user by entering the psql shell first: sudo -u postgres psql and then run the command ALTER USER postgres WITH PASSWORD 'set your password here';. Inside the shell, exit with \q. The two main configuration files you need to know about are postgresql.conf which controls all instance parameters, and pg_hba.conf which controls which clients can connect and with which authentication method. Both files are located at /etc/postgresql/16/main/ on Ubuntu 24.04 (the version number in the path will change depending on which major version apt installs).
For a Droplet intended to run PostgreSQL seriously, you should choose a spec with at least 2GB RAM or more, because PostgreSQL needs memory for shared buffers, connections, and work memory for complex queries. The smallest Droplet with 512MiB RAM is only suitable for experimentation or learning. If you want to allow external clients to connect, you need to edit listen_addresses = '*' in postgresql.conf and add authorization lines in pg_hba.conf for specific IPs, along with opening Cloud Firewall only to port 5432 from trusted IPs. Never open port 5432 to the internet without IP restrictions, as it's a vulnerability that automated scanners search for constantly.
- ติดตั้งด้วย
sudo apt install postgresql postgresql-contrib - ตรวจสถานะ service ด้วย
sudo systemctl status postgresql - ไฟล์ config หลักอยู่ที่
/etc/postgresql/<version>/main/ - Droplet ที่รันจริงควรมี RAM อย่างน้อย 2GB ขึ้นไป
- ห้ามเปิดพอร์ต 5432 สู่อินเทอร์เน็ตแบบไม่จำกัด IP
ค่าพื้นฐานที่ควรปรับ: shared_buffers, work_mem
จากที่เราทดสอบจริง — ค่า default ของ PostgreSQL หลังติดตั้งใหม่ตั้งไว้แบบระมัดระวังมาก เพราะออกแบบให้รันได้แม้บนเครื่องแรมจำกัด ทำให้ Droplet ที่มี RAM หลาย GB แทบไม่ได้ใช้ทรัพยากรเต็มประสิทธิภาพถ้าไม่แก้ค่าเอง พารามิเตอร์แรกที่ควรปรับคือ shared_buffers ซึ่งเป็นหน่วยความจำ ที่ PostgreSQL ใช้แคชข้อมูลตาราง/index ไว้ในโปรเซส แนวทางทั่วไปคือตั้งไว้ที่ประมาณ 25% ของ RAM ทั้งหมด เช่น Droplet 4GB ($24/เดือน ตามราคา DigitalOcean Basic Droplet) ควรตั้ง shared_buffers = 1GB ส่วน Droplet 2GB ($12/เดือน) ตั้งไว้ที่ shared_buffers = 512MB ก็เพียงพอ
พารามิเตอร์ที่สองคือ effective_cache_size ซึ่งไม่ได้จองหน่วยความจำจริง แต่เป็นตัวบอก query planner ว่าระบบปฏิบัติการมี แคชไฟล์ (OS page cache) ให้ใช้ประมาณเท่าไร ช่วยให้ planner ตัดสินใจเลือกใช้ index แทน sequential scan ได้แม่นยำขึ้น ค่าที่แนะนำคือ 50-75% ของ RAM เช่น effective_cache_size = 3GB บน Droplet 4GB
พารามิเตอร์ที่สามคือ work_mem ซึ่งเป็นหน่วยความจำต่อการ sort หรือ hash หนึ่งครั้งในแต่ละ query ค่านี้ต้องระวังเป็นพิเศษ เพราะ query หนึ่งตัวอาจใช้ work_mem หลายครั้งพร้อมกัน (เช่น sort + hash join) และ connection แต่ละตัวก็แยกกัน ถ้าตั้งสูงเกินไปบน เซิร์ฟเวอร์ที่มี connection เยอะจะทำให้ RAM หมดและ OOM killer ฆ่าโปรเซส postgres ทิ้ง ค่าเริ่มต้นที่ปลอดภัยสำหรับ Droplet ทั่วไปคือ work_mem = 16MB ถึง work_mem = 32MB ส่วน maintenance_work_mem ที่ใช้ตอนสร้าง index หรือรัน VACUUM สามารถตั้งสูงกว่าได้ เช่น maintenance_work_mem = 256MB เพราะรันไม่บ่อยและไม่กระทบทุก connection
หลังแก้ค่าทั้งหมดในไฟล์ postgresql.conf ต้อง reload หรือ restart service ด้วย sudo systemctl restart postgresql การเปลี่ยนบางค่าเช่น shared_buffers ต้อง restart เท่านั้น reload ไม่พอ ตรวจสอบค่าที่ใช้งานจริงหลังแก้ได้ด้วยคำสั่งใน psql: SHOW shared_buffers;
shared_buffers≈ 25% ของ RAM เครื่อง เช่น 1GB บน Droplet 4GBeffective_cache_size≈ 50-75% ของ RAMwork_memตั้งต่ำไว้ก่อน (16-32MB) ป้องกัน RAM หมดเมื่อมีหลาย connectionmaintenance_work_memตั้งสูงกว่าได้ เพราะใช้เฉพาะตอนสร้าง index/VACUUM
Index และ Query Performance เบื้องต้น
การปรับค่าพารามิเตอร์ระดับเซิร์ฟเวอร์ช่วยได้ระดับหนึ่ง แต่ปัญหาประสิทธิภาพส่วนใหญ่ที่เจอจริงในโปรดักชันมาจาก query ที่ไม่มี index รองรับ เครื่องมือที่ต้องใช้เป็นประจำคือ EXPLAIN ANALYZE วางไว้หน้าคำสั่ง SELECT เพื่อดู execution plan จริงพร้อมเวลาที่ใช้ แต่ละขั้นตอน เช่น EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 42; ถ้าผลลัพธ์แสดง Seq Scan on orders แทนที่จะเป็น Index Scan บนตารางที่มีข้อมูลหลายแสนแถว นั่นคือสัญญาณว่าต้องสร้าง index
การสร้าง index ทำได้ง่ายด้วย CREATE INDEX idx_orders_customer_id ON orders (customer_id); แต่บนตารางที่มีข้อมูลจำนวนมาก และรับ traffic อยู่ตลอด การสร้าง index แบบปกติจะล็อกตารางไม่ให้ write ระหว่างสร้าง ควรใช้ CREATE INDEX CONCURRENTLY แทน เพื่อสร้าง index โดยไม่บล็อก write แม้จะใช้เวลานานกว่าเล็กน้อย
อีกเครื่องมือที่มีประโยชน์มากคือ extension pg_stat_statements ที่ติดมากับ postgresql-contrib เปิดใช้งานโดยเพิ่มบรรทัด shared_preload_libraries = 'pg_stat_statements' ใน postgresql.conf แล้ว restart จากนั้นสร้าง extension ด้วย CREATE EXTENSION pg_stat_statements; เมื่อเปิดใช้แล้วสามารถ query ตาราง pg_stat_statements เพื่อดูว่า query ไหนถูกเรียก บ่อยที่สุดและใช้เวลารวมมากที่สุด ช่วยให้โฟกัสการ optimize ไปที่จุดที่คุ้มค่าจริง แทนการเดาสุ่ม
นอกจาก index แล้ว การดูแล table statistics ก็สำคัญไม่แพ้กัน PostgreSQL ใช้สถิติจาก ANALYZE ในการตัดสินใจเลือก plan ถ้าสถิติเก่าหรือไม่ตรงกับข้อมูลจริง planner อาจเลือก plan ที่แย่ ปกติ autovacuum จะรัน ANALYZE ให้อัตโนมัติ แต่หลังโหลดข้อมูลจำนวนมาก ครั้งเดียว (bulk import) ควรรัน ANALYZE table_name; เองทันทีเพื่อให้สถิติอัปเดตโดยไม่ต้องรอรอบ autovacuum ถัดไป
- ใช้
EXPLAIN ANALYZEดู execution plan ก่อนเดาว่าปัญหาคืออะไร - Seq Scan บนตารางใหญ่ = สัญญาณว่าต้องสร้าง index
- สร้าง index บนตารางที่ใช้งานจริงด้วย
CREATE INDEX CONCURRENTLY - เปิด
pg_stat_statementsเพื่อหา query ที่กินเวลารวมมากที่สุด
เมื่อไหร่ควรย้ายไปใช้ Managed Database
การดูแล PostgreSQL เองบน Droplet ให้ความยืดหยุ่นสูงสุดและต้นทุนต่ำที่สุดในช่วงแรก แต่มีจุดที่ควรพิจารณาย้ายไปใช้ DigitalOcean Managed Database แทน โดยเฉพาะเมื่อทีมเริ่มใช้เวลาดูแลเรื่อง backup, patching เวอร์ชัน, และ monitoring มากกว่าที่ควร Managed PostgreSQL ของ DigitalOcean เริ่มต้นที่แผน Basic 1vCPU/1GiB RAM พร้อม storage 10-30GiB ราคา $15.15 ต่อเดือน (ข้อมูล ณ กรกฎาคม 2026 ตรวจสอบราคาล่าสุดที่เว็บผู้ให้บริการ) ซึ่งแพงกว่า Droplet เปล่าขนาดใกล้เคียงกัน แต่แลกมาด้วยระบบ automated backup รายวัน, point-in-time recovery, การอัปเดต security patch อัตโนมัติ และตัวเลือกเพิ่ม standby node สำหรับ high availability ที่ต้องทำเอง ค่อนข้างซับซ้อนถ้าติดตั้งบน Droplet ด้วยตนเอง สัญญาณที่บ่งบอกว่าถึงเวลาย้ายมี 3 อย่างหลัก อย่างแรกคือเมื่อ downtime ของฐานข้อมูลเริ่มมีผลกระทบทางธุรกิจจริง เช่น ระบบ e-commerce ที่รับคำสั่งซื้อตลอดเวลา การมี standby node พร้อม automatic failover ของ Managed Database ลดความเสี่ยงตรงนี้ได้มาก อย่างที่สองคือ เมื่อทีมไม่มีคนที่ถนัดด้าน database administration พอจะดูแล vacuum, index bloat, และ security patch ได้สม่ำเสมอ Managed Database จัดการเรื่องเหล่านี้ให้อัตโนมัติ อย่างที่สามคือเมื่อต้องการ compliance หรือ audit log ระดับที่ตั้งค่าเองบน Droplet ทำได้ยาก ในทางกลับกัน ถ้าโปรเจกต์ยังอยู่ในช่วงพัฒนา งบจำกัด หรือทีมมีความรู้ PostgreSQL อยู่แล้วและต้องการควบคุม extension/configuration แบบละเอียด (เช่นต้องใช้ extension ที่ Managed Database ไม่รองรับ) การดูแล PostgreSQL เองบน Droplet ยังเป็นทางเลือกที่สมเหตุสมผลกว่า หลายทีมเลือกใช้วิธีผสม คือ dev/staging รันบน Droplet เอง ส่วน production ย้ายไป Managed Database เมื่อระบบเริ่มมีผู้ใช้จริง
- Managed PostgreSQL เริ่มที่ $15.15/เดือน (1vCPU/1GiB RAM, 10-30GiB storage) — ข้อมูล ก.ค. 2026
- แลกกับ automated backup, point-in-time recovery, patch อัตโนมัติ
- เหมาะเมื่อ downtime กระทบธุรกิจจริงหรือทีมไม่มีคนดูแล DBA เต็มเวลา
- Self-host บน Droplet ยังคุ้มกว่าถ้ายังอยู่ช่วง dev/staging หรืองบจำกัด
- รูปแบบผสม: dev บน Droplet เอง, production ย้ายไป Managed Database
Backup ด้วย pg_dump และ Volume Snapshot
จากที่เราทดสอบจริง — เมื่อดูแล PostgreSQL เองบน Droplet ความรับผิดชอบเรื่อง backup ตกอยู่ที่ทีมทั้งหมด ไม่มีระบบ automated backup ในตัวเหมือน Managed Database วิธีพื้นฐานที่สุดคือใช้ pg_dump สำรองข้อมูลระดับฐานข้อมูล เช่น pg_dump -U postgres mydb > mydb_backup.sql หรือใช้ format แบบ custom ที่บีบอัดและ restore ได้ยืดหยุ่นกว่าด้วย pg_dump -U postgres -Fc mydb > mydb_backup.dump การ restore กลับทำได้ด้วย pg_restore -U postgres -d mydb mydb_backup.dump ควรตั้ง cron job ให้รัน pg_dump อัตโนมัติทุกวัน เช่น เพิ่มบรรทัดใน crontab -e: 0 2 * * * pg_dump -U postgres -Fc mydb > /backups/mydb_$(date +%F).dump และควรก็อปปี้ไฟล์ backup ออกไปเก็บนอก Droplet ด้วย เช่นอัปโหลดไป DigitalOcean Spaces เพื่อไม่ให้ backup หายพร้อมกับ Droplet
อีกชั้นหนึ่งที่ควรใช้ร่วมกันคือ DigitalOcean Volumes และ Volume Snapshot ถ้าเก็บ data directory ของ PostgreSQL ไว้บน Volume แยก ต่างหากจาก boot disk ของ Droplet (ราคา Volume $0.10 ต่อ GiB ต่อเดือน) จะสามารถสร้าง snapshot ของ Volume นั้นได้โดยตรง ราคา Volume snapshot อยู่ที่ $0.06 ต่อ GiB ต่อเดือน ถูกกว่าการเก็บ backup ไฟล์ดิบเปล่าๆ ในบางกรณี และ snapshot ทำได้เร็วกว่า pg_dump มากสำหรับฐานข้อมูลขนาดใหญ่ เพราะเป็นการ snapshot ระดับ block storage ไม่ใช่การ export ข้อมูลทีละแถว
ข้อควรระวังคือ Volume snapshot เป็น crash-consistent ไม่ใช่ application-consistent ถ้าสร้าง snapshot ขณะ PostgreSQL กำลังเขียนข้อมูล อยู่ อาจได้ backup ที่ต้องผ่านกระบวนการ crash recovery ตอน restore แนวทางที่ปลอดภัยกว่าคือรัน SELECT pg_start_backup('snapshot'); ก่อนสร้าง snapshot แล้วตามด้วย SELECT pg_stop_backup(); หลังสร้างเสร็จ (หรือใช้ pg_basebackup สำหรับ physical backup ที่ครบถ้วนกว่า) แนวทางที่ปลอดภัยและตรวจสอบง่ายที่สุดสำหรับทีมส่วนใหญ่คือใช้ pg_dump เป็นหลักสำหรับ backup ระดับข้อมูล และใช้ Volume Snapshot เป็นชั้นป้องกันเพิ่มเติมสำหรับกู้คืนทั้งระบบอย่างรวดเร็ว
pg_dump -U postgres -Fc mydb > mydb_backup.dumpสำรองข้อมูลระดับฐานข้อมูล- ตั้ง cron job รัน pg_dump อัตโนมัติทุกวัน แล้วเก็บไฟล์ออกไปนอก Droplet
- Volume snapshot ราคา $0.06/GiB/เดือน เร็วกว่า pg_dump มากสำหรับฐานข้อมูลขนาดใหญ่
- Volume snapshot เป็น crash-consistent ควรใช้ pg_start_backup/pg_stop_backup ร่วมด้วย
เมื่อไหร่ควรใช้ฟีเจอร์นี้ (Use Case จริง)
การ tuning PostgreSQL เองบน Droplet เหมาะกับสถานการณ์เฉพาะบางแบบมากกว่าจะเป็นทางเลือกที่ดีที่สุดสำหรับทุกโปรเจกต์ use case แรก ที่ชัดเจนคือแอปพลิเคชันขนาดเล็กถึงกลางที่ทีมมีความรู้ PostgreSQL อยู่แล้วและต้องการควบคุมทุกอย่างเอง เช่น SaaS ที่เพิ่งเริ่มต้นและ ต้องการประหยัดต้นทุนโครงสร้างพื้นฐานในช่วงแรก การรัน PostgreSQL บน Droplet 4GB ราคา $24 ต่อเดือนที่ tune ค่าเองอย่างเหมาะสม มัก รองรับ traffic ได้มากพอสำหรับผู้ใช้หลักพันถึงหลักหมื่นราย โดยต้นทุนต่ำกว่า Managed Database ที่เริ่มต้น $15.15 ต่อเดือนสำหรับสเปก ที่เล็กกว่า use case ที่สองคือทีมที่ต้องการใช้ extension ของ PostgreSQL ที่ Managed Database ไม่รองรับ หรือ configuration พิเศษที่ต้องแก้ค่า ระดับ kernel/filesystem ร่วมด้วย เช่นงานที่ต้องปรับแต่ง PostgreSQL ให้ทำงานร่วมกับระบบ analytics เฉพาะทาง หรือทีมที่ทำ database replication แบบ custom ที่ต้องควบคุม WAL และ replication slot เองโดยตรง use case ที่สามคือการใช้เป็นสภาพแวดล้อม dev/staging ที่ไม่จำเป็นต้องมี SLA สูง การรัน PostgreSQL บน Droplet เดียวกับที่รันแอปพลิเคชัน หรือ Droplet แยกราคาถูกช่วยประหยัดค่าใช้จ่ายเมื่อเทียบกับสร้าง Managed Database แยกสำหรับทุก environment และยังฝึกให้ทีมเข้าใจ พฤติกรรมของ PostgreSQL จริงในระดับที่ลึกกว่าการใช้ผ่าน managed service ตลอดเวลา ส่วน use case ที่ไม่แนะนำคือระบบที่รายได้ธุรกิจผูกกับ uptime ของฐานข้อมูลโดยตรง หรือทีมที่ไม่มีเวลาติดตาม security patch และ vacuum อย่างสม่ำเสมอ กรณีเหล่านี้ต้นทุนที่ประหยัดได้จากการดูแลเองมักน้อยกว่าความเสี่ยงและเวลาที่ต้องเสียไปเมื่อเกิดปัญหา
- SaaS/แอปเริ่มต้นที่ต้องการประหยัดต้นทุนและทีมมีความรู้ PostgreSQL อยู่แล้ว
- งานที่ต้องใช้ extension หรือ configuration พิเศษที่ Managed Database ไม่รองรับ
- สภาพแวดล้อม dev/staging ที่ไม่จำเป็นต้องมี SLA สูง
- ไม่เหมาะกับระบบที่รายได้ผูกกับ uptime ฐานข้อมูลโดยตรงและทีมไม่มีเวลาดูแล
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
ที่พบบ่อยในทางปฏิบัติ — ข้อผิดพลาดที่พบบ่อยที่สุดในการ tune PostgreSQL บน Droplet คือการตั้ง shared_buffers หรือ work_mem สูงเกินไป โดยลืมคำนวณว่า connection หลายตัวพร้อมกันจะรวมกันใช้ RAM เท่าไร ผลคือระบบปฏิบัติการเรียก OOM killer มาฆ่าโปรเซส postgres ทิ้งกลาง คัน ทำให้ฐานข้อมูล crash แบบไม่มีสัญญาณเตือนล่วงหน้า วิธีแก้คือคำนวณแบบระมัดระวัง ตั้ง max_connections ให้พอดีกับที่ใช้จริง (ไม่ควรเกิน 100-200 สำหรับ Droplet ทั่วไป) และใช้ connection pooler อย่าง PgBouncer แทนการเปิด connection ตรงจาก application จำนวนมาก
ข้อผิดพลาดที่สองคือ Droplet ที่มี RAM น้อย (512MiB-1GiB) ไม่ได้เปิด swap ไว้ เมื่อ PostgreSQL หรือ process อื่นใช้ RAM เกิน ระบบจะ crash ทันทีแทนที่จะช้าลงแบบค่อยเป็นค่อยไป ควรเปิด swap อย่างน้อย 1-2GB ด้วย fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile แม้ swap จะไม่ใช่ทางแก้ระยะยาวสำหรับงานหนัก แต่ช่วยกัน crash แบบฉับพลันได้
ข้อผิดพลาดที่สามคือลืมตรวจสอบพื้นที่ดิสก์ของ Droplet หรือ Volume ที่เก็บ data directory เมื่อดิสก์เต็ม PostgreSQL จะปฏิเสธ write ทันทีและอาจทำให้ transaction ที่ค้างอยู่เสียหาย ควรตั้ง Alert Policy ผ่าน DigitalOcean Monitoring (ฟรี) ให้แจ้งเตือนเมื่อ disk usage เกิน 80% ล่วงหน้าก่อนดิสก์เต็มจริง
ข้อผิดพลาดที่สี่คือปล่อยให้ autovacuum ทำงานช้ากว่าอัตราการเปลี่ยนแปลงข้อมูล ทำให้เกิด table bloat และ index bloat สะสม ส่งผลให้ query ช้าลงเรื่อยๆ โดยไม่มีสาเหตุชัดเจน ตรวจสอบได้ด้วยการดู n_dead_tup ในตาราง pg_stat_user_tables ถ้าตัวเลขสูงผิดปกติ เทียบกับ n_live_tup ให้ปรับค่า autovacuum_vacuum_scale_factor ให้ต่ำลงสำหรับตารางที่ update บ่อย
- shared_buffers/work_mem สูงเกินไปรวมกับ connection เยอะ ทำให้ OOM killer ฆ่า postgres — ใช้ PgBouncer จำกัด connection
- Droplet RAM น้อยไม่มี swap — เปิด swap 1-2GB ป้องกัน crash แบบฉับพลัน
- ดิสก์เต็มทำให้ write ถูกปฏิเสธ — ตั้ง Alert Policy แจ้งเตือนเมื่อ disk usage เกิน 80%
- Autovacuum ตามไม่ทันทำให้เกิด table/index bloat — ตรวจ n_dead_tup แล้วปรับ autovacuum_vacuum_scale_factor
แนวทางปฏิบัติที่ดีที่สุด (Best Practices)
การ tuning ที่ดีต้องเริ่มจากการวัดผลก่อนและหลังเสมอ ไม่ใช่แก้ค่าตามความรู้สึก ใช้เครื่องมือ pgbench ที่ติดตั้งมาพร้อม postgresql-contrib สร้าง benchmark ก่อนแก้ค่าด้วย pgbench -i mydb แล้วรันทดสอบด้วย pgbench -c 10 -j 2 -T 60 mydb จดผลลัพธ์ transactions per second ไว้ แล้วรันซ้ำหลังปรับค่าแต่ละครั้งเพื่อเปรียบเทียบ วิธีนี้ทำให้รู้แน่ชัดว่าค่าที่ปรับช่วยจริงหรือไม่ แทนการเดา
ควรแก้ค่าทีละพารามิเตอร์และจดบันทึกเหตุผลไว้ในไฟล์ config หรือ commit message ถ้าเก็บ postgresql.conf ไว้ใน version control การเปลี่ยนหลายค่าพร้อมกันทำให้ยากต่อการหาสาเหตุเมื่อประสิทธิภาพแย่ลงแทนที่จะดีขึ้น และควรทดสอบการเปลี่ยนแปลงบน Droplet staging ก่อนนำไปใช้กับ production เสมอ
เปิดใช้ DigitalOcean Monitoring (ฟรี ไม่มีค่าใช้จ่ายเพิ่ม) เพื่อติดตาม CPU, memory, และ disk I/O ของ Droplet แบบต่อเนื่อง ตั้ง Alert Policy สำหรับ memory usage และ disk usage ล่วงหน้า เพราะปัญหาการ tune ผิดมักแสดงอาการเป็น memory usage ที่ค่อยๆ ไต่สูงขึ้น ก่อนที่จะ crash จริง การจับสัญญาณได้เร็วช่วยแก้ปัญหาก่อนเกิด downtime
สุดท้าย ควรวางแผนเส้นทางการเติบโตไว้ล่วงหน้า ไม่จำเป็นต้องดูแล PostgreSQL เองบน Droplet ไปตลอด กำหนดตัวชี้วัดชัดเจนไว้ล่วงหน้า เช่น เมื่อ traffic เกินระดับหนึ่งหรือทีมเริ่มใช้เวลาดูแลฐานข้อมูลมากกว่าพัฒนาฟีเจอร์ ให้ย้ายไปใช้ Managed Database การวางแผนล่วงหน้า แบบนี้ทำให้การย้ายระบบเป็นการตัดสินใจที่มีข้อมูลรองรับ ไม่ใช่การแก้ปัญหาเฉพาะหน้าหลังเกิด incident ไปแล้ว
- Benchmark ก่อน/หลังด้วย
pgbenchทุกครั้งที่แก้ค่า อย่าเดาว่าดีขึ้นโดยไม่วัดผล - แก้ทีละพารามิเตอร์ + จดบันทึกเหตุผล ทดสอบบน staging ก่อนเสมอ
- เปิด DigitalOcean Monitoring ฟรี ตั้ง Alert สำหรับ memory และ disk usage
คำถามที่พบบ่อย (FAQ)
shared_buffers = 1GB เหมาะสม แล้วปรับขึ้นลงตาม workload จริงหลังทดสอบด้วย pgbenchSELECT pg_reload_conf(); หรือ sudo systemctl reload postgresql ได้เลย แต่พารามิเตอร์ที่กระทบ shared memory เช่น shared_buffers, max_connections ต้อง restart service เท่านั้น