จากบทความเรื่อง Scaling PostgreSQL to power 800 million ChatGPT users
ซึ่งเป็น session หนึ่งในงาน PostgreSQL development conference 2025
เป็นการเล่าถึงการ scale PostgreSQL database เพื่อรองรับ workload ที่สูงขึ้น
สิ่งที่น่าสนใจมาก ๆ คือ ที่มาที่ไปของปัญหา และ แนวทางการแก้ไขปัญหา
มาดูกันว่าเป็นอย่างไรบ้าง ?
เอาที่ผมรู้เรื่องนะครับ !!

ระบบหลักของ OpenAI นั้นจะใช้ PostgreSQL database เป็นหลัก
ดังนั้นถ้า database มีปัญหาแล้ว ระบบล่ม และ ใช้งานไม่ได้
และแน่นอนว่ามีปัญหามาตลอดเวลา

แนวทางในการแก้ไขปัญหาคอขวดนี้

ทางทีมจึงเลือกใช้งาน database บน Azure (Geo-distributed) ซึ่งเป็น managed service
โดยใช้ database topology เป็น master-slave (Primary-Replicas)
ใช้งาน 1 primary database เท่านั้น และไม่ทำการ sharding อีกด้วย
ในส่วนของ replica database ประมาณ 50 เครื่องกระจายในแต่ละ zone ทั้งโลก
เหตุผลคือ สามารถขยายระบบเพื่อรองรับการ read และ read ได้อย่างดี
อีกอย่างถ้าทำ shardding แล้ว จะทำให้ระบบซับซ้อนขึ้น และกระทบต่อระบบอื่น ๆ อีก
ดังนั้นตอนนี้จึงยังไม่ทำ แต่ในอนาคตก็เป็นอีกหนึ่งทางเลือกเช่นกัน

แต่เมื่อใช้งานไปสักระยะหนึ่งก็เจอปัญหาใหม่คือ
ระบบมีการ write ข้อมูลที่สูงขึ้น
ซึ่งส่งผลให้ระบบที่ใช้งานอยู่นั้น ไม่สามารถรองรับได้ !!
เพราะว่า การทำงานของระบบงานนั้นมีปัญหาคอขวดเพียบ

หนึ่งในนั้นมันคือ PostgreSQL ที่มีปัญหาในการรองรับการ write ข้อมูลจำนวนมาก ๆ
ซึ่งมาจากการออกแบบ MVVC ของ database นั่นเอง เช่น

  • เมื่อ table มีขนาดใหญ่ขึ้น ก็ทำ index มากขึ้น
  • การ tuning autovacuum ก็ยากและซับซ้อนมาก
  • การจัดการและดูแลพวก index ต่าง ๆ ก็ใช้เวลานาน
  • ไม่พอ ในการ replica ข้อมูลไปยังเครื่องอื่นก็ช้าอีกด้วย (replica lag)
  • การใช้งาน bandwidth ของ network ก็สูงขึ้น จนเต็มอีก !!

แนวทางการลดปัญหาคือ ลดการใช้งานบน Primary database

ยกตัวอย่างเช่น

  • ย้ายการ write data ไปยังระบบอื่น ซึ่งเป็น Shard system ภายใน ที่คล้าย ๆ กับ Azure Cosmos DB
  • ลดจำนวนการ write ในฝั่ง application ลง แถมยังเจอ bug ว่ามีการ write ที่ไม่จำเป็นจำนวนมาก
  • ใช้เทคนิด Lazy write และใช้งาน rate limit เข้ามาช่วยเหลือ
  • ส่วนการ read ให้ไปเครื่อง Replica ให้มากที่สุด
  • ต้อง monitor การทำงานให้ดี เช่น การดูว่า index ที่สร้างนั้นถูกใช้งานหรือไม่ ถ้าไม่หรือน้อยแล้ว ให้ทำการ disable ก่อนเพื่อดูผล จากนั้นถ้าไม่ส่งผล ก็ทำการลบมันซะ

ต่อมาปรับปรุงการ read อีกด้วย เพื่อลดการใช้งานลงไป

ยกตัวอย่างเช่น

  • ใช้ rate limit ในทุก ๆ ระดับ ทั้ง application ทั้งการสร้าง database connection ก็จัดการที่ connection pool ด้วย pgbouuncer
  • กำหนด timeout ในการ run query ด้วยเสมอทั้ง transaction, statement และ client timeout
  • ลดการ run query ที่ join table กันเยอะ ๆ ซึ่งเจอเยอะสุดคือ 12 tables (ลูกอีช่าง join มาก ๆ)
  • ในการใช้งาน ORM (Object Relation Mapping) ต้องระวังให้มาก ๆ เพราะว่า ถ้าใช้ไม่ดี มักจะสร้าง query ที่แย่ ๆ ออกมา
  • มีการทำ caching ด้วย Redis แต่ก็มีปัญหาตามมาเมื่อไม่เจอข้อมูลใน cache ก็จะวิ่งไป database แต่ถ้า query นาน ๆ จนเกิน timeout ก็จะ retry อีก !!! นี่มันปัญหาที่น่ากลัวมาก ๆ (เพื่อนล้มแล้สเราต้องกระทืบซ้ำ !!)

และแน่นอนว่ายังคงปรับปรุงระบบงาน
เพื่อรองรับจำนวนข้อมูลและผู้ใช้งานที่สูงขึ้นอย่างต่อเนื่อง