วิธีทำให้ Postgres ช้าลง
(byteofdev.com)- แนะนำแนวทางการทดลองเกี่ยวกับ ชุดพารามิเตอร์ที่สามารถทำให้ประสิทธิภาพของ Postgres ลดลงอย่างรุนแรง
- โดยทั่วไปคือการจูนย้อนทางของ แคช, อินเด็กซ์, WAL, I/O และองค์ประกอบอื่น ๆ
- ปรับ shared_buffers, autovacuum และออปชันที่เกี่ยวข้องกับ WAL แบบสุดขั้ว จนทำให้ TPS ลดลง 42,000 เท่า
- นำฟีเจอร์ใหม่อย่าง io_method และ io_workers ใน Postgres 18/19 มาใช้เพื่อทดลองบังคับข้อจำกัด I/O แบบเธรดเดียว
- ผลการทดลองพิสูจน์ว่า เพียงแค่ไฟล์ตั้งค่า Postgres ก็สามารถทำให้ประสิทธิภาพลดลงอย่างสุดขั้วได้
ภาพรวม
บทความนี้เป็นการทดลองที่ทำตรงข้ามกับการจูน Postgres เพื่อให้เร็วขึ้น โดยตั้งเป้าเพียงอย่างเดียวคือ ทำให้ช้าลง ผ่านการเปลี่ยนค่า config ของ PostgreSQL เท่านั้น เพื่อกดประสิทธิภาพลงให้สุดขีด
การทดสอบอิงกับ TPC-C workload ของ BenchBase (128 คลังสินค้า, 100 คอนเนกชัน, แต่ละคอนเนกชันพยายามทำธุรกรรมได้สูงสุด 10,000 ครั้งต่อวินาที, ใช้ Postgres 19devel รุ่นล่าสุด, Ryzen 7950x, RAM 32GB, SSD 2TB, รัน 120 วินาที)
ที่ค่าเริ่มต้น ประสิทธิภาพอยู่ที่ 7082 TPS และมีการสังเกตทีละขั้นว่าการปรับพารามิเตอร์แต่ละตัวทำให้ช้าลงได้มากแค่ไหน
ลดการแคชอย่างหนัก
- Postgres ใช้ แคชที่ทรงพลัง (shared_buffers) เพื่อช่วยลด disk I/O
- เมื่อลด shared_buffers จากค่าเริ่มต้น (10GB) เหลือ 8MB ค่า TPS ลดลงเหลือประมาณ 1/7 (1052 TPS)
- พบว่า อัตรา cache hit ลดจาก 99.90% เหลือ 70.52% และจำนวน read syscall เพิ่มขึ้นมากกว่า 300 เท่า
- มีความพยายามลดลงถึง 128kB แต่ Postgres อนุญาตขั้นต่ำเพียงราว 2MB ทำให้ TPS ลดลงต่อเหลือ 485 TPS
เพิ่มงานเบื้องหลัง (จูน autovacuum)
- ปรับ ค่าเกณฑ์ทั้งหมดที่เกี่ยวข้องกับ autovacuum ให้ต่ำสุด จน vacuum ทำงานแทบทุกครั้งที่มีงาน
- ชุดค่าเช่น
autovacuum_vacuum_insert_threshold=1,autovacuum_naptime=1 - ทำให้ vacuum วนทำงานแทบทุก 1 วินาที แม้แทบไม่มีงานจริงให้ทำ
- ชุดค่าเช่น
- ระหว่างนี้ยัง ลด maintenance_work_mem เหลือ 128kB และเปิด logging ของ autovacuum ทั้งหมด
- ผลคือ TPS ลดลงเหลือ 293 (น้อยกว่า 1/20 ของเดิม)
- ยืนยันผ่าน log แบบเรียลไทม์ของ autovacuum ว่างานเบื้องหลังที่ถี่ผิดปกติคือสาเหตุของประสิทธิภาพที่ลดลง
ทำให้งานเขียน WAL (Write-Ahead Log) แย่ที่สุด
- ปรับ พารามิเตอร์ที่เกี่ยวข้องกับ WAL ให้แย่ที่สุดทั้งหมด
wal_writer_flush_after=0,wal_writer_delay=1,wal_sync_method=open_datasyncเป็นต้น- บังคับ checkpoint ทุก 30 วินาที และคง
min_wal_size/max_wal_size=32MBให้ต่ำสุด - ตั้ง
wal_level=logical,wal_log_hints=onเพื่อบันทึกข้อมูลที่ไม่จำเป็นลง WAL เพิ่มเติม - เปิดภาระเพิ่มเติมอย่าง
track_wal_io_timing,summarize_wal
- ผลคือ TPS ลดลงเหลือ 98 (น้อยกว่า 1/70 ของเดิม)
- จาก log พบพฤติกรรมผิดปกติ เช่น checkpoint เกิดซ้ำทุกไม่กี่ร้อย ms
ตัดผลของอินเด็กซ์ออก
- ตั้งค่าการใช้อินเด็กซ์ให้ถูก คำนวณต้นทุนสูงสุด (
random_page_cost=1e300,cpu_index_tuple_cost=1e300) จนเท่ากับปิดการใช้อินเด็กซ์ในทางปฏิบัติ - เพิ่ม
shared_buffersกลับเป็น 8MB (เพื่อความเสถียร) แล้ว TPS ลดลงเหลือ 0.87 (ช้าลง 7,000 เท่า)
บังคับ I/O แบบเธรดเดียว
- ใช้ฟีเจอร์ใหม่ของ Postgres 18+
- ตั้ง
io_method=worker,io_workers=1เพื่อ บังคับให้ I/O ทั้งหมดวิ่งผ่าน worker thread เดียว - TPS ลดลงต่อเหลือ 0.016 (ช้าลง 42,000 เท่า)
- ในการทดลอง 100 คอนเนกชันเป็นเวลา 120 วินาที สำเร็จเพียง 11 ธุรกรรมเท่านั้น
บทสรุปและแนวทางการทำซ้ำ
- พิสูจน์ว่าเพียงการปรับพารามิเตอร์ 32 รายการ ก็สามารถทำให้ฐานข้อมูล production อยู่ในสภาพเกือบ "เป็นอัมพาต" ได้
- สามารถเร่งให้ประสิทธิภาพลดลงอย่างรุนแรงได้ด้วยการแตะเพียงค่าใน
postgresql.conf - ผู้ที่ต้องการทำซ้ำการทดลองควรอ้างอิง BenchBase Postgres, สภาพแวดล้อม TPC-C ที่ระบุไว้ และรายการค่าตั้งค่าทั้งหมด
- ยังไม่ได้รวมพารามิเตอร์เสริมหรือความพยายามอื่น ๆ ในการทำให้ช้าลงเพิ่มเติม
รายการพารามิเตอร์โดยสรุป
shared_buffers = 8MB- ค่า thresholds/scale_factor ที่เกี่ยวกับ autovacuum = ปรับต่ำสุดช่วง 0~1
- ค่าใช้จ่าย, หน่วยความจำ และ log ที่เกี่ยวกับ vacuum: ปรับให้ต่ำสุด/สูงสุดตามกรณี
- ค่าที่เกี่ยวกับ WAL เช่น sync/flush/log/level: ตั้งให้คงความช้า
- ค่าอินเด็กซ์
random_page_cost,cpu_index_tuple_cost: ตั้งเป็น1e300 io_method = worker,io_workers = 1- รายละเอียดค่าอื่น ๆ ดูจากรายการในเนื้อหา
ปิดท้าย
- เพียงแค่ไฟล์
postgresql.confก็สามารถก่อให้เกิดการลดลงของประสิทธิภาพอย่างหนักได้ - ในงานจริง ชุดค่านี้มีคุณค่าในฐานะตัวอย่างกลับทางสำหรับการปรับปรุงประสิทธิภาพอย่างมีประสิทธิผล
- บทความจบลงด้วยการกล่าวถึงการหยุดทดลองเพราะผู้เขียนปวดหลัง
2 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ยอดเยี่ยมมากครับ ชอบแนวทางแบบนี้มาก