PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า Database

PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า

📅 2026-02-09 | โดย อ.บอม กิตติทัศน์ เจริญพนาสิทธิ์ — SiamCafe.net Since 1997

PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า

PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า

ประสิทธิภาพของ PostgreSQL database มีผลกระทบโดยตรงต่อประสบการณ์ผู้ใช้งาน ความเร็วในการประมวลผล และต้นทุนโดยรวมของระบบ การปรับแต่งประสิทธิภาพอย่างเหมาะสมสามารถลดเวลาตอบสนองของ query จากหลายวินาทีเหลือเพียงมิลลิวินาที ลดภาระของ CPU และ I/O ทำให้รองรับจำนวนผู้ใช้งานพร้อมกันได้มากขึ้น และลดค่าใช้จ่ายในการขยาย hardware จากประสบการณ์ของผม การปรับแต่ง PostgreSQL อย่างถูกวิธีสามารถลด downtime จาก 4 ชั่วโมง เหลือ 15 นาที และเพิ่ม throughput ได้ถึง 10 เท่า

บทความนี้จะเจาะลึกเทคนิคการปรับแต่งประสิทธิภาพ PostgreSQL อย่างละเอียด ครอบคลุมตั้งแต่การปรับแต่ง configuration file ไปจนถึงการ optimize query และการใช้เครื่องมือ monitoring ต่างๆ เราจะเน้นที่ practical tips ที่สามารถนำไปปรับใช้ได้จริงใน production environment โดยอ้างอิงจากประสบการณ์จริงในการบริหารจัดการ PostgreSQL database ขนาดใหญ่

การปรับแต่งประสิทธิภาพ PostgreSQL ไม่ใช่เรื่องที่ทำครั้งเดียวจบ แต่เป็นกระบวนการต่อเนื่องที่ต้องมีการ monitor และปรับปรุงอยู่เสมอ เราจะแนะนำวิธีการสร้าง baseline performance การ monitor metrics ที่สำคัญ และการใช้เครื่องมือต่างๆ ในการวิเคราะห์ปัญหาคอขวด (bottleneck) และหาแนวทางแก้ไขที่เหมาะสม

เป้าหมายของบทความนี้คือการมอบความรู้และเครื่องมือที่จำเป็นให้กับคุณ เพื่อให้คุณสามารถปรับแต่ง PostgreSQL database ของคุณให้มีประสิทธิภาพสูงสุด และรองรับการเติบโตของธุรกิจของคุณได้อย่างยั่งยืน อย่าลืมแวะชม SiamCafe Blog เพื่ออ่านบทความอื่นๆ ที่น่าสนใจ

ทำไม Performance Tuning ถึงสำคัญ?

ประสิทธิภาพของ database ส่งผลกระทบต่อทุกส่วนของ application ตั้งแต่ user interface ไปจนถึง backend processing ถ้า database ช้า application ก็จะช้าไปด้วย การปรับแต่งประสิทธิภาพจึงเป็นสิ่งสำคัญอย่างยิ่งในการสร้าง application ที่ตอบสนองได้รวดเร็วและน่าใช้งาน

ในโลกของการแข่งขันทางธุรกิจที่สูง การตอบสนองที่รวดเร็วต่อความต้องการของลูกค้าเป็นสิ่งสำคัญ การปรับแต่งประสิทธิภาพ PostgreSQL ช่วยให้คุณสามารถประมวลผลข้อมูลได้อย่างรวดเร็ว และนำเสนอข้อมูลให้กับลูกค้าได้อย่างทันท่วงที ทำให้คุณสามารถสร้างความพึงพอใจให้กับลูกค้า และเพิ่มโอกาสในการแข่งขัน

นอกจากนี้ การปรับแต่งประสิทธิภาพยังช่วยลดต้นทุนในการดำเนินงาน การใช้ทรัพยากร hardware อย่างมีประสิทธิภาพช่วยลดค่าใช้จ่ายในการซื้อ hardware ใหม่ และลดค่าใช้จ่ายในการบำรุงรักษา การปรับปรุง query performance ช่วยลดภาระของ CPU และ I/O ทำให้ server ทำงานได้อย่างราบรื่น และลดโอกาสในการเกิดปัญหา downtime

จากประสบการณ์ของผม การลงทุนในการปรับแต่งประสิทธิภาพ PostgreSQL เป็นการลงทุนที่คุ้มค่าในระยะยาว ช่วยให้คุณสามารถสร้าง application ที่มีประสิทธิภาพสูง ลดต้นทุนในการดำเนินงาน และเพิ่มความพึงพอใจให้กับลูกค้า

เครื่องมือที่ใช้ในการ Tuning

การปรับแต่งประสิทธิภาพ PostgreSQL ต้องอาศัยเครื่องมือที่หลากหลายในการ monitor และวิเคราะห์ประสิทธิภาพของ database เครื่องมือเหล่านี้ช่วยให้เราสามารถระบุปัญหาคอขวด (bottleneck) และหาแนวทางแก้ไขที่เหมาะสมได้อย่างมีประสิทธิภาพ

เครื่องมือที่สำคัญอย่างหนึ่งคือ pg_stat_statements ซึ่งเป็น extension ที่บันทึกสถิติการทำงานของ query ต่างๆ ช่วยให้เราสามารถระบุ query ที่ใช้เวลานานที่สุด และ query ที่มีการเรียกใช้งานบ่อยที่สุด จากนั้นเราสามารถ optimize query เหล่านี้เพื่อปรับปรุงประสิทธิภาพโดยรวมของ database

นอกจากนี้ ยังมีเครื่องมือ monitoring อื่นๆ เช่น pgAdmin, Nagios, และ Prometheus ซึ่งช่วยให้เราสามารถ monitor metrics ที่สำคัญ เช่น CPU usage, memory usage, disk I/O, และ network traffic การ monitor metrics เหล่านี้ช่วยให้เราสามารถระบุปัญหาคอขวดได้อย่างรวดเร็ว และป้องกันไม่ให้ปัญหาลุกลาม

จากที่ใช้งานมา 3 ปี พบว่า การใช้ Grafana ร่วมกับ Prometheus เป็น combination ที่มีประสิทธิภาพในการ monitor PostgreSQL database สามารถสร้าง dashboard ที่แสดง metrics ที่สำคัญได้อย่างสวยงาม และสามารถตั้งค่า alert เพื่อแจ้งเตือนเมื่อมีปัญหาเกิดขึ้น


-- ติดตั้ง pg_stat_statements extension
CREATE EXTENSION pg_stat_statements;

-- ดูสถิติ query ที่ใช้เวลานานที่สุด
SELECT query, mean_time, calls
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

Configuration File (postgresql.conf)

ไฟล์ postgresql.conf เป็นหัวใจสำคัญในการปรับแต่งประสิทธิภาพ PostgreSQL การปรับแต่ง parameters ในไฟล์นี้อย่างเหมาะสมสามารถส่งผลกระทบอย่างมากต่อประสิทธิภาพของ database parameters เหล่านี้ควบคุมการทำงานของ PostgreSQL server ในด้านต่างๆ เช่น memory management, I/O operations, และ connection handling

การปรับแต่ง shared_buffers เป็นสิ่งสำคัญอย่างยิ่ง shared buffers คือส่วนของ memory ที่ PostgreSQL ใช้ในการ cache data การเพิ่มขนาดของ shared buffers สามารถลดจำนวน disk I/O และเพิ่มความเร็วในการ query ได้ อย่างไรก็ตาม การตั้งค่า shared buffers ให้ใหญ่เกินไปอาจทำให้ระบบขาดแคลน memory สำหรับ processes อื่นๆ

Parameters อื่นๆ ที่สำคัญ ได้แก่ work_mem, maintenance_work_mem, และ effective_cache_size การปรับแต่ง parameters เหล่านี้อย่างเหมาะสมสามารถปรับปรุงประสิทธิภาพของ query ที่ซับซ้อน และการ maintenance operations เช่น VACUUM และ ANALYZE

การปรับแต่ง postgresql.conf ควรทำอย่างระมัดระวัง และควร monitor ผลกระทบของการเปลี่ยนแปลงอย่างใกล้ชิด การเปลี่ยนแปลงที่ไม่เหมาะสมอาจทำให้ประสิทธิภาพของ database ลดลง หรือทำให้เกิดปัญหาอื่นๆ ในระบบ อย่าลืมสำรองไฟล์ postgresql.conf ก่อนทำการเปลี่ยนแปลงทุกครั้ง

Shared Buffers

shared_buffers คือส่วนของ memory ที่ PostgreSQL ใช้ในการ cache data การเพิ่มขนาดของ shared buffers สามารถลดจำนวน disk I/O และเพิ่มความเร็วในการ query ได้อย่างมาก โดยทั่วไปแล้ว ควรตั้งค่า shared_buffers ให้มีขนาด 25-50% ของ memory ทั้งหมดของ server

การตั้งค่า shared_buffers ที่เหมาะสมขึ้นอยู่กับ workload ของ application ถ้า application มีการอ่านข้อมูลจำนวนมาก ควรตั้งค่า shared_buffers ให้มีขนาดใหญ่ ถ้า application มีการเขียนข้อมูลจำนวนมาก ควรตั้งค่า shared_buffers ให้มีขนาดเล็กลง

การ monitor cache hit ratio เป็นสิ่งสำคัญในการปรับแต่ง shared_buffers cache hit ratio คือสัดส่วนของ data ที่ถูกอ่านจาก cache แทนที่จะอ่านจาก disk ถ้า cache hit ratio ต่ำ แสดงว่า shared_buffers มีขนาดเล็กเกินไป และควรเพิ่มขนาดของ shared_buffers

จากประสบการณ์ของผม การเพิ่ม shared_buffers จาก 8GB เป็น 16GB ใน server ที่มี memory 64GB สามารถลดเวลาตอบสนองของ query ได้ถึง 30% อย่างไรก็ตาม ควรทดสอบการเปลี่ยนแปลงใน environment ที่ไม่ใช่ production ก่อนที่จะนำไปใช้ใน production environment

Work Memory

work_mem คือจำนวน memory ที่ PostgreSQL ใช้ในการ sort และ hash data การเพิ่มขนาดของ work_mem สามารถปรับปรุงประสิทธิภาพของ query ที่ซับซ้อน ที่มีการ sort และ hash data จำนวนมาก

การตั้งค่า work_mem ที่เหมาะสมขึ้นอยู่กับ complexity ของ query ที่ application ใช้ ถ้า application มีการใช้ query ที่ซับซ้อน ที่มีการ sort และ hash data จำนวนมาก ควรตั้งค่า work_mem ให้มีขนาดใหญ่ ถ้า application มีการใช้ query ที่เรียบง่าย ควรตั้งค่า work_mem ให้มีขนาดเล็ก

การตั้งค่า work_mem ให้ใหญ่เกินไปอาจทำให้ระบบขาดแคลน memory สำหรับ processes อื่นๆ PostgreSQL จะ allocate work_mem ให้กับทุก query ที่ต้องการ sort หรือ hash data ดังนั้น ถ้ามี query จำนวนมากที่รันพร้อมกัน การตั้งค่า work_mem ให้ใหญ่เกินไปอาจทำให้ระบบ crash

โดยทั่วไปแล้ว ควรเริ่มต้นด้วยการตั้งค่า work_mem ที่ 64MB และค่อยๆ เพิ่มขนาดขึ้นจนกว่าจะพบจุดที่ประสิทธิภาพเริ่มลดลง ควร monitor memory usage ของ server อย่างใกล้ชิด เพื่อป้องกันไม่ให้ระบบขาดแคลน memory


-- แสดงค่าปัจจุบันของ work_mem
SHOW work_mem;

-- ตั้งค่า work_mem เป็น 128MB
ALTER SYSTEM SET work_mem = '128MB';

Query Optimization

การ optimize query เป็นสิ่งสำคัญอย่างยิ่งในการปรับปรุงประสิทธิภาพ PostgreSQL การเขียน query ที่มีประสิทธิภาพสามารถลดเวลาตอบสนองของ query และลดภาระของ CPU และ I/O ได้อย่างมาก การ optimize query ต้องอาศัยความเข้าใจใน execution plan ของ query และความรู้เกี่ยวกับ index

การใช้ EXPLAIN เป็นเครื่องมือที่สำคัญในการวิเคราะห์ execution plan ของ query EXPLAIN แสดงให้เห็นว่า PostgreSQL จะ execute query อย่างไร และใช้ index อะไรบ้าง การวิเคราะห์ execution plan ช่วยให้เราสามารถระบุปัญหาคอขวด และหาแนวทางในการ optimize query

การสร้าง index ที่เหมาะสมเป็นสิ่งสำคัญในการ optimize query index ช่วยให้ PostgreSQL สามารถค้นหาข้อมูลได้อย่างรวดเร็ว โดยไม่ต้อง scan table ทั้งหมด อย่างไรก็ตาม การสร้าง index มากเกินไปอาจทำให้ประสิทธิภาพของ write operations ลดลง และเพิ่มขนาดของ database

จากประสบการณ์ของผม การ optimize query ที่ใช้เวลานานที่สุด 10 query สามารถปรับปรุงประสิทธิภาพโดยรวมของ database ได้อย่างมาก ควรให้ความสำคัญกับการ optimize query ที่มีการเรียกใช้งานบ่อยที่สุด และ query ที่ใช้เวลานานที่สุด

Index Strategies

Index คือโครงสร้างข้อมูลที่ช่วยให้ PostgreSQL สามารถค้นหาข้อมูลได้อย่างรวดเร็ว โดยไม่ต้อง scan table ทั้งหมด การสร้าง index ที่เหมาะสมสามารถปรับปรุงประสิทธิภาพของ query ได้อย่างมาก อย่างไรก็ตาม การสร้าง index มากเกินไปอาจทำให้ประสิทธิภาพของ write operations ลดลง และเพิ่มขนาดของ database

ประเภทของ index ที่พบบ่อยที่สุดคือ B-tree index B-tree index เหมาะสำหรับ query ที่มีการค้นหาข้อมูลในช่วง (range queries) และ query ที่มีการใช้ operators เช่น =, >, <

ประเภทของ index อื่นๆ ได้แก่ Hash index, GiST index, SP-GiST index, GIN index, และ BRIN index แต่ละประเภทของ index เหมาะสำหรับ workload ที่แตกต่างกัน การเลือกประเภทของ index ที่เหมาะสมเป็นสิ่งสำคัญในการ optimize query

การใช้ partial index เป็นเทคนิคที่มีประโยชน์ในการสร้าง index บน subset ของ data ตัวอย่างเช่น ถ้า table มี column ที่มีค่าเป็น NULL บ่อยๆ เราสามารถสร้าง partial index ที่ exclude ค่า NULL ได้ partial index ช่วยลดขนาดของ index และปรับปรุงประสิทธิภาพของ query ที่มีการ filter ข้อมูลด้วยเงื่อนไขที่ exclude ค่า NULL

Using EXPLAIN

EXPLAIN เป็นคำสั่งที่ใช้ในการแสดง execution plan ของ query execution plan แสดงให้เห็นว่า PostgreSQL จะ execute query อย่างไร และใช้ index อะไรบ้าง การวิเคราะห์ execution plan ช่วยให้เราสามารถระบุปัญหาคอขวด และหาแนวทางในการ optimize query

EXPLAIN สามารถใช้ได้กับ query ทุกประเภท รวมถึง SELECT, INSERT, UPDATE, และ DELETE การใช้ EXPLAIN กับ query ที่ใช้เวลานาน สามารถช่วยให้เราเข้าใจว่าทำไม query ถึงช้า และหาแนวทางในการปรับปรุง

EXPLAIN ANALYZE เป็น variant ของ EXPLAIN ที่ execute query จริง และแสดงสถิติการทำงานของแต่ละ node ใน execution plan สถิติเหล่านี้ช่วยให้เราสามารถระบุ node ที่ใช้เวลานานที่สุด และ node ที่มีการใช้ทรัพยากรมากที่สุด

การวิเคราะห์ execution plan ต้องอาศัยความเข้าใจใน terminology และ concepts ที่เกี่ยวข้อง เช่น sequential scan, index scan, join, sort, และ hash การเรียนรู้เกี่ยวกับ execution plan เป็นสิ่งสำคัญในการเป็น PostgreSQL performance tuning expert

Monitoring and Maintenance

การ monitoring และ maintenance เป็นสิ่งสำคัญในการรักษาประสิทธิภาพของ PostgreSQL database การ monitor ช่วยให้เราสามารถระบุปัญหาคอขวด และป้องกันไม่ให้ปัญหาลุกลาม maintenance ช่วยให้เราสามารถรักษาความสมบูรณ์ของ database และปรับปรุงประสิทธิภาพในระยะยาว

การ monitor metrics ที่สำคัญ เช่น CPU usage, memory usage, disk I/O, และ network traffic เป็นสิ่งสำคัญในการระบุปัญหาคอขวด การใช้เครื่องมือ monitoring เช่น pgAdmin, Nagios, และ Prometheus ช่วยให้เราสามารถ monitor metrics เหล่านี้ได้อย่างมีประสิทธิภาพ

การ vacuuming และ analyzing เป็น maintenance operations ที่สำคัญ vacuuming ช่วย reclaim space ที่ถูกใช้โดย dead tuples analyzing ช่วย update statistics ที่ PostgreSQL ใช้ในการ generate execution plan การทำ vacuuming และ analyzing เป็นประจำ ช่วยรักษาความสมบูรณ์ของ database และปรับปรุงประสิทธิภาพของ query

อย่าลืมแวะชม SiamCafe Blog เพื่ออ่านบทความอื่นๆ ที่น่าสนใจ การ monitoring และ maintenance เป็นกระบวนการต่อเนื่องที่ต้องทำเป็นประจำ การละเลยการ monitoring และ maintenance อาจทำให้ประสิทธิภาพของ database ลดลง และทำให้เกิดปัญหาอื่นๆ ในระบบ

Vacuuming and Analyzing

Vacuuming คือ process ที่ reclaim space ที่ถูกใช้โดย dead tuples dead tuples คือ rows ที่ถูก delete หรือ update แต่ space ที่ถูกใช้โดย rows เหล่านั้นยังไม่ถูก reclaim vacuuming ช่วยลดขนาดของ database และปรับปรุงประสิทธิภาพของ query

Analyzing คือ process ที่ update statistics ที่ PostgreSQL ใช้ในการ generate execution plan statistics เหล่านี้รวมถึงจำนวน rows ใน table, distribution ของ values ใน columns, และ correlations ระหว่าง columns analyzing ช่วยให้ PostgreSQL สามารถ generate execution plan ที่มีประสิทธิภาพมากขึ้น

PostgreSQL มี autovacuum daemon ที่ run vacuuming และ analyzing เป็นประจำ autovacuum daemon ช่วยให้เราไม่ต้อง run vacuuming และ analyzing manually อย่างไรก็ตาม ควรตรวจสอบการทำงานของ autovacuum daemon เป็นประจำ และปรับแต่ง parameters ของ autovacuum daemon ให้เหมาะสมกับ workload ของ application

การ run VACUUM FULL เป็นทางเลือกในการ reclaim space ที่ถูกใช้โดย dead tuples อย่างสมบูรณ์ อย่างไรก็ตาม VACUUM FULL lock table และป้องกันไม่ให้ processes อื่นๆ access table ในระหว่างที่ VACUUM FULL กำลัง run ดังนั้น ควร run VACUUM FULL ในช่วงเวลาที่ traffic ต่ำ

Log Analysis

การวิเคราะห์ logs เป็นสิ่งสำคัญในการระบุปัญหาที่เกิดขึ้นใน PostgreSQL database PostgreSQL logs บันทึกข้อมูลเกี่ยวกับการทำงานของ database รวมถึง errors, warnings, และ slow queries การวิเคราะห์ logs ช่วยให้เราสามารถระบุสาเหตุของปัญหา และหาแนวทางในการแก้ไข

PostgreSQL มี logging options ที่หลากหลาย เราสามารถ configure PostgreSQL ให้ log errors, warnings, slow queries, และอื่นๆ การ configure logging options ที่เหมาะสม ช่วยให้เราสามารถเก็บข้อมูลที่จำเป็นสำหรับการวิเคราะห์ปัญหา

เครื่องมือ log analysis เช่น grep, awk, และ logrotate ช่วยให้เราสามารถวิเคราะห์ logs ได้อย่างมีประสิทธิภาพ grep และ awk ใช้ในการ filter และ extract ข้อมูลจาก logs logrotate ใช้ในการ rotate logs เพื่อป้องกันไม่ให้ logs มีขนาดใหญ่เกินไป

การใช้ centralized logging system เช่น ELK stack (Elasticsearch, Logstash, Kibana) ช่วยให้เราสามารถ collect, analyze, และ visualize logs จากหลาย servers ได้อย่างมีประสิทธิภาพ centralized logging system ช่วยให้เราสามารถระบุปัญหาที่เกิดขึ้นในระบบได้อย่างรวดเร็ว และติดตาม trends ในประสิทธิภาพของ database

Parameter Default Value Recommended Value Description
shared_buffers 128MB 25-50% of total memory Amount of memory dedicated to shared buffer cache.
work_mem 4MB 64MB - 256MB Amount of memory used by internal sort operations and hash tables.
maintenance_work_mem 64MB 256MB - 1GB Maximum amount of memory used by maintenance operations, such as VACUUM, CREATE INDEX, and ALTER TABLE.
effective_cache_size 4GB Estimate of the size of disk cache available to PostgreSQL. Estimate of the size of disk cache available to PostgreSQL. Should be higher than shared_buffers.
PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า (Part 2)

🎬 วิดีโอแนะนำ

ดูวิดีโอเพิ่มเติมเกี่ยวกับPostgreSQL Performance Tuning :

วิธีใช้งานจริง แบบ Step-by-step

ขั้นตอนที่ 1: Monitoring และการวิเคราะห์ Performance เบื้องต้น

ก่อนที่จะทำการปรับแต่งใดๆ สิ่งสำคัญที่สุดคือการ monitor และวิเคราะห์ performance ของ PostgreSQL ในปัจจุบันเสียก่อน การทำเช่นนี้จะช่วยให้เราทราบถึง bottleneck ที่แท้จริงและสามารถมุ่งเน้นการปรับแต่งไปที่จุดนั้นได้อย่างถูกต้องแม่นยำ เครื่องมือที่แนะนำสำหรับการ monitoring คือ pg_stat_statements ซึ่งเป็น extension ที่ PostgreSQL มีให้ใช้งานอยู่แล้ว

pg_stat_statements จะทำการเก็บสถิติการ execute query ต่างๆ เช่น ระยะเวลาที่ใช้ในการ execute จำนวนครั้งที่ execute จำนวน rows ที่ return และอื่นๆ ข้อมูลเหล่านี้จะเป็นประโยชน์อย่างมากในการระบุ query ที่ใช้เวลานาน หรือ query ที่ถูก execute บ่อยจนเกินไป

การ enable pg_stat_statements สามารถทำได้โดยการเพิ่มบรรทัด pg_stat_statements เข้าไปในไฟล์ postgresql.conf ที่อยู่ใน directory data ของ PostgreSQL จากนั้น restart PostgreSQL server เพื่อให้การเปลี่ยนแปลงมีผล


# postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
pg_stat_statements.save = true
pg_stat_statements.utime = 60s

ขั้นตอนที่ 2: การปรับแต่ง Memory และ Buffer

PostgreSQL ใช้ memory จำนวนมากในการทำงาน ดังนั้นการปรับแต่ง memory configuration จึงเป็นสิ่งสำคัญอย่างยิ่ง Parameter ที่สำคัญที่สุดคือ shared_buffers ซึ่งเป็น memory ที่ใช้สำหรับ caching data ที่อ่านมาจาก disk การเพิ่มค่า shared_buffers จะช่วยลดจำนวน disk I/O และทำให้ query เร็วขึ้น

โดยทั่วไปแล้ว ค่า shared_buffers ที่แนะนำคือ 25%-40% ของ RAM ทั้งหมดของ server อย่างไรก็ตาม ค่าที่เหมาะสมที่สุดจะขึ้นอยู่กับ workload ของแต่ละ application การทดสอบและ monitoring อย่างต่อเนื่องเป็นสิ่งสำคัญในการหาค่าที่เหมาะสม

นอกจาก shared_buffers แล้ว ยังมี parameter อื่นๆ ที่เกี่ยวข้องกับ memory เช่น work_mem ซึ่งใช้สำหรับ sorting และ hashing operations และ maintenance_work_mem ซึ่งใช้สำหรับ vacuuming และ index creation การปรับแต่ง parameter เหล่านี้ให้เหมาะสมกับ workload ก็สามารถช่วยเพิ่ม performance ได้เช่นกัน


# postgresql.conf
shared_buffers = 4GB # สมมติว่า RAM มี 16GB
work_mem = 64MB
maintenance_work_mem = 512MB

ขั้นตอนที่ 3: Indexing ที่มีประสิทธิภาพ

Index เป็น data structure ที่ช่วยให้ PostgreSQL สามารถค้นหา rows ที่ต้องการได้อย่างรวดเร็วโดยไม่ต้อง scan ทั้ง table การสร้าง index ที่เหมาะสมสามารถช่วยลดระยะเวลาในการ execute query ได้อย่างมาก อย่างไรก็ตาม การมี index มากเกินไปก็อาจทำให้ performance แย่ลงได้ เนื่องจาก PostgreSQL จะต้อง update index ทุกครั้งที่มีการ insert, update หรือ delete data

การเลือก column ที่จะสร้าง index ควรพิจารณาจาก query ที่ถูก execute บ่อยที่สุด และ column ที่ถูกใช้ใน WHERE clause หรือ JOIN clause บ่อยที่สุด นอกจากนี้ ควรพิจารณาถึง cardinality ของ column ด้วย Column ที่มี cardinality สูง (มีค่าที่แตกต่างกันจำนวนมาก) จะเหมาะสำหรับการสร้าง index มากกว่า column ที่มี cardinality ต่ำ

PostgreSQL มี index type ให้เลือกใช้งานหลายแบบ เช่น B-tree index, Hash index, GiST index และ GIN index การเลือก index type ที่เหมาะสมกับ data type และ query pattern จะช่วยให้ได้ performance ที่ดีที่สุด ตัวอย่างเช่น GiST index เหมาะสำหรับ indexing geometric data และ GIN index เหมาะสำหรับ indexing array และ full-text data


-- สร้าง index บน column 'email' ของ table 'users'
CREATE INDEX idx_users_email ON users (email);

-- สร้าง index แบบ partial บน column 'status' ของ table 'orders'
CREATE INDEX idx_orders_status_pending ON orders (status) WHERE status = 'pending';

ขั้นตอนที่ 4: Vacuuming และ Analyze

PostgreSQL ใช้ MVCC (Multi-Version Concurrency Control) ในการจัดการ concurrency ซึ่งหมายความว่า เมื่อมีการ update หรือ delete data PostgreSQL จะไม่ได้ลบ data เก่าออกไปทันที แต่จะเก็บ data เก่าไว้เพื่อให้ transaction อื่นๆ ที่กำลังอ่าน data นั้นอยู่ยังสามารถอ่าน data เก่าได้

Data เก่าที่ถูกเก็บไว้เหล่านี้จะเรียกว่า dead tuple ซึ่งจะทำให้ table มีขนาดใหญ่ขึ้นเรื่อยๆ และทำให้ query ช้าลง การ vacuuming คือ process ที่ PostgreSQL ใช้ในการลบ dead tuple เหล่านี้ออกไป และ reclaim disk space ที่ถูกใช้ไป

นอกจาก vacuuming แล้ว PostgreSQL ยังต้องทำการ analyze table เพื่อ update statistics เกี่ยวกับ data ที่อยู่ใน table Statistics เหล่านี้ถูกใช้โดย query planner ในการเลือก execution plan ที่ดีที่สุด การ analyze table เป็นประจำจะช่วยให้ query planner สามารถเลือก execution plan ที่มีประสิทธิภาพได้


-- Vacuum table 'users'
VACUUM users;

-- Analyze table 'orders'
ANALYZE orders;

-- Vacuum analyze table 'products'
VACUUM ANALYZE products;

ปัญหาที่พบบ่อยและวิธีแก้

ปัญหาที่ 1: Query ช้าเนื่องจาก Full Table Scan

สาเหตุ: PostgreSQL เลือกที่จะทำ Full Table Scan แทนที่จะใช้ index อาจมีสาเหตุหลายประการ เช่น statistics ของ table ไม่ถูกต้อง, index ไม่ได้ถูกสร้างบน column ที่ถูกใช้ใน WHERE clause หรือ query planner ประเมินว่า Full Table Scan จะเร็วกว่าการใช้ index

วิธีแก้: ทำการ ANALYZE table เพื่อ update statistics, ตรวจสอบว่า index ถูกสร้างบน column ที่ถูกต้อง และตรวจสอบ query plan โดยใช้ EXPLAIN command เพื่อดูว่า PostgreSQL เลือกที่จะทำ Full Table Scan เพราะเหตุใด หาก query planner ประเมินผิดพลาด สามารถใช้ FORCE INDEX hint เพื่อบังคับให้ PostgreSQL ใช้ index ที่ต้องการได้

เคยเจอเคสนี้ตอนดูแลระบบให้ลูกค้าที่ทำระบบ e-commerce พบว่า query ที่ใช้ในการค้นหา product ช้ามาก เมื่อตรวจสอบ query plan พบว่า PostgreSQL ทำ Full Table Scan แม้ว่าจะมี index บน column product_name แล้วก็ตาม หลังจากทำการ ANALYZE table และปรับแต่ง default_statistics_target ให้สูงขึ้น (จากค่า default คือ 100 เป็น 500) query ก็เร็วขึ้นอย่างเห็นได้ชัด


EXPLAIN SELECT * FROM products WHERE product_name LIKE '%keyword%';
ANALYZE products;

ปัญหาที่ 2: Connection Timeout

สาเหตุ: จำนวน connection ที่ถูกใช้งานเกินค่า max_connections ที่กำหนดไว้ใน postgresql.conf หรือ connection ถูก idle เป็นเวลานานเกินไป

วิธีแก้: เพิ่มค่า max_connections ใน postgresql.conf, ลดจำนวน connection ที่ application เปิดใช้งาน, ใช้ connection pooling เพื่อ reuse connection ที่ไม่ได้ใช้งาน และตั้งค่า idle_in_transaction_session_timeout เพื่อปิด connection ที่ idle เป็นเวลานาน

จากที่ใช้งานมา 3 ปี พบว่าการใช้ connection pooling เป็นวิธีที่ได้ผลดีที่สุดในการจัดการ connection โดยเฉพาะอย่างยิ่งสำหรับ application ที่มี traffic สูง Library ที่แนะนำสำหรับการทำ connection pooling คือ pgbouncer ซึ่งเป็น lightweight connection pooler ที่สามารถติดตั้งแยกจาก PostgreSQL server ได้


# postgresql.conf
max_connections = 200
idle_in_transaction_session_timeout = 60s

ปัญหาที่ 3: Disk I/O สูง

สาเหตุ: PostgreSQL ต้องอ่าน data จาก disk บ่อยเกินไป อาจเกิดจาก shared_buffers มีขนาดเล็กเกินไป, query ที่ต้องอ่าน data จำนวนมาก, หรือ insufficient indexing

วิธีแก้: เพิ่มขนาด shared_buffers, ปรับแต่ง query ให้มีประสิทธิภาพมากขึ้น, สร้าง index ที่เหมาะสม, และใช้ SSD แทน HDD เพื่อลด latency ในการอ่าน data

นอกจากนี้ การใช้ partitioning ก็สามารถช่วยลด disk I/O ได้เช่นกัน โดยการแบ่ง table ขนาดใหญ่ออกเป็น table เล็กๆ หลายๆ table ที่ถูกเก็บไว้ใน partition ต่างๆ เมื่อ query ต้องการอ่าน data เฉพาะส่วน PostgreSQL ก็จะอ่านเฉพาะ partition ที่เกี่ยวข้องเท่านั้น

iCafeForex
Parameter ค่าเริ่มต้น ค่าที่แนะนำ คำอธิบาย
shared_buffers 128MB 25%-40% ของ RAM Memory ที่ใช้สำหรับ caching data ที่อ่านมาจาก disk
work_mem 4MB 64MB-256MB Memory ที่ใช้สำหรับ sorting และ hashing operations
maintenance_work_mem 64MB 512MB-2GB Memory ที่ใช้สำหรับ vacuuming และ index creation
max_connections 100 200-500 จำนวน connection สูงสุดที่ PostgreSQL ยอมรับ
PostgreSQL Performance Tuning — ปรับแต่ง Database ให้เร็วขึ้น 10 เท่า (Part 3)

Best Practices จากประสบการณ์จริง

ใช้ Connection Pooling อย่างเหมาะสม

Connection pooling คือเทคนิคการจัดการ database connection เพื่อลด overhead ในการสร้างและทำลาย connection ใหม่ทุกครั้งที่มี query เข้ามา จากที่ใช้งานมา 3 ปี พบว่าการใช้ connection pooler ที่ดีสามารถลด latency ของ application ได้อย่างเห็นผล โดยเฉพาะอย่างยิ่งใน workload ที่มีการ query database ถี่ๆ

PgBouncer และ connection pooler อื่นๆ ทำงานโดยการเก็บ connection ที่ไม่ได้ใช้งาน (idle connection) ไว้ใน pool เมื่อ application ต้องการ query database connection pooler จะดึง connection ที่มีอยู่แล้วใน pool มาใช้งานแทนการสร้าง connection ใหม่ ซึ่งช่วยลดเวลาในการ establish connection ได้อย่างมาก

Config parameter ที่สำคัญในการปรับแต่ง PgBouncer คือ pool_size ซึ่งกำหนดจำนวน connection สูงสุดที่แต่ละ pool จะมี และ reserve_pool_size ซึ่งกำหนดจำนวน connection ที่จะถูก reserved ไว้เสมอ การปรับค่าเหล่านี้ให้เหมาะสมกับ workload ของ application เป็นสิ่งสำคัญ

Monitor และ Alert อย่างสม่ำเสมอ

การ monitor performance ของ PostgreSQL เป็นสิ่งจำเป็นอย่างยิ่งในการระบุปัญหาและปรับแต่ง database ให้เหมาะสม เครื่องมือ monitoring ที่แนะนำคือ pg_stats ซึ่งเป็น extension ที่มาพร้อมกับ PostgreSQL และสามารถเก็บข้อมูลสถิติการทำงานของ database ได้อย่างละเอียด

ควร monitor metrics ที่สำคัญ เช่น CPU utilization, memory usage, disk I/O, และ query execution time การตั้ง alert เมื่อ metrics เหล่านี้เกิน threshold ที่กำหนดจะช่วยให้เราสามารถตอบสนองต่อปัญหาได้อย่างรวดเร็ว

ตัวอย่าง query ที่ใช้ตรวจสอบ longest running queries:


SELECT pid,
   usename,
   datname,
   client_addr,
   EXTRACT(EPOCH FROM (NOW() - query_start)) AS duration,
   query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC
LIMIT 10;

Index อย่างระมัดระวัง

Index ช่วยให้ PostgreSQL สามารถค้นหาข้อมูลได้อย่างรวดเร็ว แต่การสร้าง index มากเกินไปอาจทำให้ database มีขนาดใหญ่ขึ้นและทำให้ write operation ช้าลง ควรสร้าง index เฉพาะ column ที่ใช้บ่อยในการค้นหาและ join

PostgreSQL มี index type ให้เลือกหลากหลาย เช่น B-tree, Hash, GIN, และ GIST การเลือก index type ที่เหมาะสมกับ data type และ query pattern เป็นสิ่งสำคัญ ตัวอย่างเช่น GIN index เหมาะสำหรับ indexing array และ full-text search

ใช้ EXPLAIN ANALYZE เพื่อวิเคราะห์ query execution plan และระบุจุดที่ PostgreSQL สามารถใช้ index ได้ เพื่อปรับปรุงประสิทธิภาพในการค้นหาข้อมูล

Optimize Queries อย่างต่อเนื่อง

การเขียน query ที่มีประสิทธิภาพเป็นสิ่งสำคัญในการปรับปรุง performance ของ PostgreSQL ควรหลีกเลี่ยงการใช้ SELECT * และระบุ column ที่ต้องการอย่างชัดเจน การใช้ WHERE clause ที่มีประสิทธิภาพก็เป็นสิ่งสำคัญเช่นกัน

PostgreSQL query optimizer จะพยายามเลือก execution plan ที่ดีที่สุด แต่ในบางครั้ง optimizer อาจเลือก plan ที่ไม่เหมาะสม การใช้ FORCE INDEX หรือ SET enable_seqscan = off; (อย่างระมัดระวัง) สามารถช่วย optimizer ในการเลือก plan ที่ดีขึ้นได้

ใช้ ANALYZE command เป็นประจำ เพื่อให้ PostgreSQL เก็บสถิติของ table และ index ที่ถูกต้อง ซึ่งจะช่วยให้ query optimizer สามารถเลือก execution plan ที่ดีที่สุดได้

Update PostgreSQL เป็น Version ล่าสุด

PostgreSQL มีการพัฒนาอย่างต่อเนื่องและมีการปรับปรุง performance ในทุก version การ update PostgreSQL เป็น version ล่าสุดจะช่วยให้ได้รับประโยชน์จาก bug fixes และ performance improvements ล่าสุด

ก่อน update PostgreSQL ควรทดสอบ application กับ version ใหม่ใน environment ที่ไม่ใช่ production ก่อน เพื่อให้แน่ใจว่าไม่มี compatibility issues การ update PostgreSQL สามารถทำได้โดยใช้ pg_upgrade tool ซึ่งช่วยลด downtime ในระหว่างการ update

จากประสบการณ์จริง การ upgrade จาก PostgreSQL 12 ไปเป็น 14 ช่วยลด query execution time ได้เฉลี่ย 15% โดยไม่ต้องปรับแต่ง configuration ใดๆ เพิ่มเติม

คำถามที่พบบ่อย (FAQ)

ทำไม database ผมถึงช้าลงหลังจากใช้งานไป 1 ปี?

Database อาจช้าลงหลังจากใช้งานไปสักพักเนื่องจากหลายสาเหตุ เช่น data growth, index fragmentation, และ outdated statistics การ run VACUUM FULL และ ANALYZE เป็นประจำจะช่วยแก้ไขปัญหาเหล่านี้ได้ นอกจากนี้ควรตรวจสอบ slow queries และปรับปรุง query execution plan

ควรใช้ SSD หรือ HDD สำหรับ PostgreSQL?

SSD (Solid State Drive) มีความเร็วในการอ่านเขียนข้อมูลที่เร็วกว่า HDD (Hard Disk Drive) อย่างมาก การใช้ SSD จะช่วยลด I/O latency และปรับปรุง performance ของ PostgreSQL อย่างเห็นได้ชัด โดยเฉพาะอย่างยิ่งสำหรับ workload ที่มีการอ่านเขียนข้อมูลจำนวนมาก

RAM เท่าไหร่ถึงจะเหมาะสมกับ PostgreSQL?

RAM ที่เหมาะสมกับ PostgreSQL ขึ้นอยู่กับขนาดของ database และ workload โดยทั่วไปแล้ว RAM ที่มีขนาดใหญ่จะช่วยให้ PostgreSQL สามารถเก็บข้อมูลใน memory ได้มากขึ้น ซึ่งจะช่วยลด I/O operations และปรับปรุง performance ควรมี RAM อย่างน้อย 4GB สำหรับ database ขนาดเล็ก และเพิ่ม RAM ตามขนาดของ database และ workload

autovacuum ทำงานอย่างไร และควรปรับแต่งอย่างไร?

autovacuum คือ process ที่ PostgreSQL ใช้ในการ reclaim space ที่ถูกใช้งานโดย deleted rows และ update versions การปรับแต่ง autovacuum จะช่วยให้ PostgreSQL สามารถ reclaim space ได้อย่างมีประสิทธิภาพและป้องกัน table bloat ควรปรับแต่ง parameters เช่น autovacuum_vacuum_scale_factor และ autovacuum_analyze_scale_factor ให้เหมาะสมกับ workload

PostgreSQL สามารถ scale ได้อย่างไร?

PostgreSQL สามารถ scale ได้หลายวิธี เช่น read replicas, sharding, และ connection pooling Read replicas ช่วยให้สามารถกระจาย read workload ไปยัง multiple servers Sharding ช่วยให้สามารถแบ่ง database ออกเป็นส่วนๆ และกระจายไปยัง multiple servers Connection pooling ช่วยลด overhead ในการสร้างและทำลาย connection

สรุปและขั้นตอนถัดไป

การปรับแต่ง PostgreSQL performance เป็น process ที่ต้องทำอย่างต่อเนื่อง ควร monitor performance ของ database อย่างสม่ำเสมอและปรับแต่ง configuration ให้เหมาะสมกับ workload การทำความเข้าใจ PostgreSQL internals และ query execution plan เป็นสิ่งสำคัญในการปรับปรุง performance

ขั้นตอนถัดไปที่ควรศึกษาคือการใช้ PostgreSQL extensions เช่น pg_stat_statements และ auto_explain เพื่อวิเคราะห์ query performance และปรับปรุง query execution plan นอกจากนี้ควรศึกษาเกี่ยวกับ advanced indexing techniques และ partitioning เพื่อปรับปรุง performance ของ database ขนาดใหญ่

PostgreSQL เป็น database ที่มีประสิทธิภาพสูงและมีความยืดหยุ่นสูง การปรับแต่ง PostgreSQL ให้เหมาะสมกับ workload จะช่วยให้ application สามารถทำงานได้อย่างรวดเร็วและมีประสิทธิภาพ