Generated by Answer me with HTML 0.5.2 · 2026-10-19 18:41 · ★ Star on GitHub
ผลวัด load ฐานข้อมูล PROD — ลด M60 → M50 ได้ไหม
v3 · ปริมาณงาน 6–19 ต.ค. 2026 + วัด load สด 2 ช่วง (ช่วงปกติ และช่วง report รัน)
ลง M50 ได้ แต่ต้องแก้ช่วง report ก่อน. ตอน report รัน แม้บน M60 ฐานข้อมูลก็ต้องอ่านจาก disk ราว 70 GB ใน 26 นาที. M40 และ M30 ยังไม่พอ.
ข้อสรุป
M50 = ได้แบบมีเงื่อนไข · M40 / M30 = ยังไม่ได้
- ช่วงปกติ M60 สบาย: อ่านจาก disk แค่ 0.47 MB/s และข้อมูลที่ใช้บ่อยอยู่ใน memory หมด.
- ช่วง report รัน (ทุก 3 ชั่วโมง) คือคอขวดจริง: อ่านจาก disk เพิ่มเป็น 46.8 MB/s (~100 เท่า). Memory cache ทั้งก้อนถูกแทนที่ ~2.2 รอบใน 26 นาที.
- Query ที่ report ใช้ช้าลงมาก: การอ่านข้อมูลคนขับเพิ่มจาก 18 ms เป็น 9–11 วินาทีต่อครั้ง.
- ปริมาณงานเดือนนี้ลดลง 10–15% จากสัปดาห์แรกไปสัปดาห์ที่สอง. load ไม่ได้โต.
- M50 มี memory ครึ่งเดียว ช่วง report จะหนักกว่านี้. ให้แก้ report และเพิ่ม index ก่อนลด tier.
ปริมาณงานต่อวัน (6–19 ต.ค.)
| รายการ | เฉลี่ย 6–12 ต.ค. | เฉลี่ย 13–18 ต.ค. | เปลี่ยน | วันสูงสุด |
|---|---|---|---|---|
| Order ใหม่ | 5,233 | 4,538 | −13% | 5,752 (11 ต.ค.) |
| รายการสินค้าใน order | 22,789 | 19,253 | −16% | 24,059 (11 ต.ค.) |
| งานส่ง (task) | 312 | 299 | −4% | 318 |
| Log กิจกรรม (ตัวแทนจำนวนการสร้าง/แก้ข้อมูล) | 661,000 | 591,000 | −11% | 687,000 (12 ต.ค.) |
| จุด GPS ของคนขับ | 73,200 | 66,100 | −10% | 77,600 |
| ข้อความ Kafka | 40,900 | 36,300 | −11% | 42,700 |
| รูป/ไฟล์แนบ | 9,960 | 9,320 | −6% | 10,500 |
นับจากเวลาที่สร้างข้อมูล (ไม่นับการแก้ไข). 19 ต.ค. ยังไม่จบวัน จึงไม่รวมในค่าเฉลี่ย.
ช่วงเวลาที่หนักที่สุดของวัน
Log กิจกรรม 17:00–18:00 (เฉลี่ย เทียบสูงสุด)70800 / max 86400 ต่อชั่วโมง
Order ใหม่ 17:00–18:00 (เฉลี่ย เทียบสูงสุด)869 / max 1118 ต่อชั่วโมง
GPS คนขับ 11:00–13:00 (เฉลี่ย เทียบสูงสุด)8870 / max 15500 ต่อชั่วโมง
- งานหนักช่วง 16:00–19:00. ค่าสูงสุดทั้งเดือนคือ 12 ต.ค. 17:00.
- 01:00–05:00 แทบไม่มีงาน. เหมาะกับการเปลี่ยน tier.
Load สด: ช่วงปกติ เทียบช่วง report
| ค่า | 17:49–17:52 (ช่วงพีค ไม่มี report) | 17:52–18:19 (report รอบ 18:00) |
|---|---|---|
| Reads | 1,342 ops/s | 2,446–3,522 ops/s |
| Writes | 217 ops/s | 300–480 ops/s |
| อ่านจาก disk เข้า memory | 0.47 MB/s | 46.8 MB/s (รวม 70.5 GB ใน 26 นาที) |
| เวลาอ่านข้อมูลคนขับต่อครั้ง | 18 ms | 9–11 วินาที |
| เวลาอ่านข้อมูลงาน/การชำระเงินต่อครั้ง | 17–33 ms | 17–41 วินาที |
| Query เล็กอื่นๆ ที่ report ไม่ใช้ | ~17 ms | ~17 ms (ไม่เปลี่ยน) |
Report รันทุก 3 ชั่วโมง (09, 12, 15, 18, 21, 00, 03, 06 น.). Report ดึงข้อมูลงาน การชำระเงิน คนขับ และผู้ใช้. ส่วนนี้ช้าลงเป็นวินาที. ส่วนอื่นของระบบยังปกติ.
Spec เทียบ load
| M60 (ปัจจุบัน) | M50 | M40 | M30 | |
|---|---|---|---|---|
| vCPU | 16 | 8 | 4 | 2 |
| RAM | 64 GB | 32 GB | 16 GB | 8 GB |
| Memory cache ของ DB | ~31.5 GB | ~15.5 GB | ~7.5 GB | ~3.5 GB |
| ช่วงปกติ | ||||
| ช่วง report (ตอนนี้) | cache ถูกแทนที่ 2.2 รอบ | ~4.5 รอบ | ||
| ช่วง report (หลังแก้) | ต้องวัดใหม่ | |||
| Disk 39 GB | ต้องขยาย |
สิ่งที่ยังไม่รู้
- ใครอ่าน log กิจกรรมทั้งก้อน: log กิจกรรมมี index แค่ _id. ช่วง 17:52–18:17 มีการอ่าน log กิจกรรมจาก disk 32.8 GB. ขนาดนี้เท่ากับอ่านทั้ง collection. Report ไม่ได้ใช้ข้อมูลชุดนี้ ต้องหาต้นทาง.
- ไม่มีค่า CPU % และ IOPS จากการวัดนี้. ต้องดูกราฟ Atlas ช่วง report.
- ค่าช่วง report มาจาก 1 รอบ (18:00).
Quick wins: แก้ที่ DB / config ไม่ต้องแก้โค้ด
| ลำดับ | สิ่งที่ทำ | ผลที่คาด | ความเสี่ยง |
|---|---|---|---|
| 1 | เพิ่ม index ที่ payments → order | report เร็วขึ้น ~58 ms ต่อ order (~70% ของเวลา report) | ต่ำ |
| 2 | เอา join ข้อมูล COD ออกจาก report (ฟิลด์ที่ join ไม่มีอยู่จริง ผลว่างทุกแถว) | เร็วขึ้น ~15 ms ต่อ order | ต่ำ ค่าที่ได้ว่างอยู่แล้ว |
| 3 | เพิ่ม index ที่ exceptions → order | เร็วขึ้น ~8 ms ต่อ order | ต่ำ |
| 4 | เพิ่ม index ที่ orders.updatedAt | report เลิกอ่าน orders ทั้งก้อน (6 GB) ทุกรอบ | ต่ำ |
| 5 | ลดช่วง report จาก 3 วัน เป็น 12 ชม. แล้วรันทุกชั่วโมง | แถวที่ประมวลผลต่อวันลด 56% ข้อมูลสดขึ้น (~1 ชม.) | ข้อมูลที่ไม่ bump updatedAt อาจค้าง ต้องมีรอบเต็มวันละครั้ง |
| 6 | เพิ่ม index ที่ key ของตาราง report และ purge orphan วันละครั้งแทนทุกรอบ | ลด ~30 วินาทีต่อรอบ | ต่ำ |
| 7 | เพิ่ม index ที่ tasks → loads / orders, loads → orders และ order logs → order | งานสร้าง task และ unhold เร็วขึ้น 200–900 ms ต่อครั้ง | ต่ำ |
| 8 | ตั้ง TTL หรือ archive log กิจกรรม 30 วัน (ตอนนี้ 32.6 GB เพิ่มวันละ ~580k แถว) | ลดข้อมูล ~17 GB และลดการอ่าน disk | ต้องตกลงระยะเก็บกับทีม audit |
| 9 | ตั้ง TTL ให้ log Kafka (8.1 GB), log pipeline (7.4 GB), log Google API (4.2 GB อยู่ใน memory 4.6 GB) | คืน memory และ disk ~15–20 GB | ต้องตกลงระยะเก็บ |
| 10 | ลบ index ที่ซ้ำ (task_id เดี่ยว ซึ่งเป็น prefix ของ index อื่น) | write เร็วขึ้นเล็กน้อย | ต่ำ |
ข้อ 1–4 รวมกันอธิบายได้ ~81 จาก 82 ms ต่อ order ที่ report ใช้. คาดว่ารอบ report จะสั้นลงจาก ~33 นาที เหลือไม่กี่นาที (ค่าประมาณ ต้องวัดซ้ำ). สร้าง index ช่วง 01:00–05:00 แบบ rolling ใน Atlas.
แก้ที่โค้ด
| ลำดับ | สิ่งที่ทำ | ผลที่คาด | ขนาดงาน |
|---|---|---|---|
| 1 | Cache ข้อมูล master ในแอป (คนขับ ผู้ใช้ สาขา รถ channel partner สกุลเงิน zone strategy) TTL 30–60 วินาที | reads ลด ~650 ops/s (49%) และเวลา DB ช่วงปกติลด ~63% | กลาง ต้อง invalidate ตอนแก้ข้อมูล |
| 2 | จำกัด populate เฉพาะฟิลด์ที่ใช้ (ตอนนี้ order 1 ใบ populate 94 path) | query ต่อ request ลดลงมาก CPU ฝั่ง Node ลดด้วย | กลาง |
| 3 | แยก route polyline และผล Google ออกจากเอกสาร task (เฉลี่ย 103 KB ต่อใบ) | task เล็กลง อ่าน list เร็วขึ้น memory ใช้น้อยลง | กลาง |
| 4 | เปลี่ยน order ที่ copy ไว้ใน stop point เป็น reference (แผน DO-ref Phase 2) | ข้อมูล stop point 13 GB เล็กลง write เบาลง | ใหญ่ |
| 5 | Report เขียนเฉพาะแถวที่เปลี่ยน แทนเขียนทุกแถวทุกรอบ | write ช่วง report ลดลงมาก | เล็ก |
| 6 | เลิกเขียน log กิจกรรมของ pipeline job/log (วัดบน bench = 54% ของ log กิจกรรม) | log กิจกรรมเพิ่มช้าลงราวครึ่งหนึ่ง | เล็ก |
| 7 | ตัด deep clone ทั้ง response และการเรียก refresh search text ทุกครั้งที่เขียน | CPU ฝั่งแอปลด จำนวน request ภายในลด | กลาง (อยู่ใน lib) |
ลำดับที่แนะนำ
- ถ้ามีปัญหา scale กลับ M60 ได้ทันที แบบไม่มี downtime.
- หาต้นทางที่อ่าน log กิจกรรมทั้งก้อนคู่กันไปด้วย.