PostgreSQL ตึงจัดกิน CPU ไปจนหมด

เปิดปีใหม่ก็ได้พบกับประสบกรณ์ตื่นเต้นทันที เมื่อได้รับแจ้งว่าเว็บระบบสารสนเทศเปรียบเทียบวัดระดับคุณภาพโรงพยาบาล เกิดอาการค้างไม่ตอบสนองผู้ใช้งาน หลังจากได้เข้าไปตรวจสอบเบื้องต้นก็พบว่า เห้ย! CPU ของเครื่อง Server กินไป 100% โดย PostgreSQL

htop ดูการใช้งาน CPU

ด้วยความที่เราก็ไม่ได้เชี่ยวชาญ PostgreSQL สิ่งแรกที่ต้องตรวจสอบก่อนก็คือ Query ใดที่ทำให้ CPU ขึ้นถึง 100% ซึ่ง PostgreSQL มีโมดูลที่ใช้มอนิเตอร์และตรวจสอบ Query อยู่แล้วนั้นก็คือ pg_stat_statements แต่โดยปกติจะถูกปิดเอาไว้ตั้งแต่ต้น ดังนั้นเราจะต้องทำการเปิดโมดูลดังกล่าวก่อนตามนี้

จากนั้นก็ค้นหา Query ที่ใช้น่าจะเป็นปัญหาโดยใช้คำสั่ง

SELECT 
  (total_time / 1000 / 60) as total, 
  (total_time/calls) as avg, 
  query 
FROM pg_stat_statements 
ORDER BY 1 DESC 
LIMIT 5;

SELECT
  max_exec_time,
  query
FROM pg_stat_statements
ORDER BY max_exec_time DESC
LIMIT 5;

ถ้าจะย้อนกลับไปอีกนิดหนึ่งก่อนที่เราจะมอนิเตอร์ Query เราได้ทำการตรวจสอบขั้นตอนการใช้งานของโปรแกรมเราด้วยที่มีการเรียกใช้งาน Query ซึ่งก็พบว่าปัญหาเกิดขึ้นในหน้า Dashboard ซึ่งจะแสดงรายงานกราฟจำนวนมาก โดย Query ที่ถูกเรียกใช้ในหน้านี้จะมีจำนวนเท่ากับจำนวน KPI ที่ผู้ใช้งานเลือกคูณด้วย 2 เพราะแต่ละ KPI จะแสดงกราฟออกมา 2 ตัว สมมติว่าผู้ใช้งานต้องการแสดง KPI 10 ตัวนั้นหมายความว่าจะมีการเรียก Query ไปที่ PostgreSQL พร้อมๆ กัน 20 ตัวเลยทีเดียว

Dashboard

ดังนั้นเพื่อช่วยลดโหลดทำการทำงานของ PostgreSQL ที่ต้อง Query ข้อมูลจำนวนมากในเวลาเดียวกัน เราจึงได้ใช้ประโยชน์จากบทความLazy Loading เข้ามาช่วยในการ Query ข้อมูลเมื่อกราฟถูกเลื่อนขึ้นมาแสดงใน viewport

ทั้งนี้ทั้งนั้นต้นเหตุของปัญหาจริงๆ ก็คือ Quey ที่กินทั้ง CPU และใช้เวลาในการดึงข้อมูลที่นาน ดังนั้นวิธีเดียวที่จะแก้ปํญหาได้จริงๆ ก็คือจัดการกับ Query เจ้าปัญหานั้นเอง

References