กลับไปหน้าบทความ
#MongoDB#Data Modeling#Database Design#Backend

MongoDB ควร Embed หรือ Reference ข้อมูลเมื่อไร

เลือกโครงสร้าง document จากรูปแบบการอ่าน ขนาดข้อมูล การเติบโต และความถี่ในการแก้ไข เพื่อเลี่ยงทั้ง query ซับซ้อนและ document ที่โตจนควบคุมไม่ได้

5 กรกฎาคม 2569อ่านประมาณ 2 นาที

แชร์บทความ

MongoDB ควร Embed หรือ Reference ข้อมูลเมื่อไร

ภาพรวม

เวลาออกแบบ MongoDB คำถามที่เจอบ่อยคือ ควร Embed ข้อมูลซ้อนไว้ใน document เดียว หรือ Reference แยกไปอีก collection ดี? คำตอบไม่ใช่ “แบบไหนถูกกว่า” แต่คือ “ข้อมูลนี้ถูกใช้งานพร้อมกันบ่อยแค่ไหน” 🙂

Embed คือเก็บข้อมูลลูกไว้ข้างใน document แม่เลย เช่น order มีรายการสินค้าอยู่ใน array items เวลาอ่าน order ก็ได้ทุกอย่างใน query เดียว ไม่ต้อง join ไม่ต้องยิงหลายรอบ เหมาะมากกับข้อมูลที่เป็นส่วนหนึ่งของกันและกัน อ่านพร้อมกันบ่อย และขนาดไม่โตแบบไม่มีเพดาน

ตัวอย่างที่ควร Embed ที่อยู่จัดส่งใน order snapshot ราคาสินค้า ณ วันที่ซื้อ คอมเมนต์สั้น ๆ ของโพสต์ที่มีจำนวนจำกัด settings ของ user พวกนี้ถ้าแยก collection อาจทำให้ระบบยุ่งขึ้นโดยไม่ได้ประโยชน์มาก เพราะเวลาจะใช้ก็ต้องดึงมาพร้อมกันอยู่ดี

Reference คือเก็บแค่ id แล้วแยกข้อมูลจริงไปอีก collection เช่น post เก็บ authorId แล้ว user อยู่ใน users collection เหมาะกับข้อมูลที่ถูกใช้ซ้ำหลายที่ เปลี่ยนแล้วอยากให้ทุกที่เห็นค่าล่าสุด หรือมีขนาดใหญ่และโตต่อเนื่อง เช่น user, product, category, payment transaction, log

กฎง่าย ๆ คือ ถ้า “เป็นของ document นี้โดยธรรมชาติ” ให้คิดถึง Embed ก่อน ถ้า “มีชีวิตของตัวเอง” ให้คิดถึง Reference ก่อน

ระวัง Embed กับ array ที่โตไม่หยุด เช่น user มี notifications เป็นหมื่นรายการ หรือ post มี comments หลักแสน แบบนี้ document จะใหญ่ขึ้นเรื่อย ๆ อัปเดตช้าลง และอาจชน limit 16MB ของ MongoDB ได้ ควรแยก collection แล้ว index ตาม parentId แทน

อีกจุดที่หลายคนพลาดคือข้อมูลที่ต้องแก้ไขบ่อย ถ้า embed ข้อมูลเดียวกันซ้ำในหลาย document เวลาแก้ครั้งหนึ่งอาจต้อง update หลายที่ เช่นชื่อสินค้าใน order เก่า จริง ๆ อาจไม่ควรแก้ เพราะ order ต้องเก็บ snapshot เดิม แต่ชื่อ user ในหลาย post อาจเป็นอีกเรื่อง ต้องตัดสินใจว่าอยากได้ “ประวัติ ณ ตอนนั้น” หรือ “ค่าปัจจุบันเสมอ”

MongoDB ไม่มี join แบบ relational เป็นหลักคิดแรก ถึงจะมี $lookup แต่ไม่ควรออกแบบให้ทุกหน้าต้อง lookup หนัก ๆ ให้เริ่มจาก query pattern หน้าจอนี้ต้องแสดงอะไร API นี้อ่านอะไรพร้อมกัน เขียนบ่อยไหม ข้อมูลโตเร็วไหม แล้วค่อยเลือกรูปแบบ

สรุปแบบใช้ได้จริง Embed เมื่อข้อมูลเล็ก อ่านพร้อมกัน และเป็นเจ้าของเดียวกัน Reference เมื่อข้อมูลใหญ่ ใช้ซ้ำ เปลี่ยนบ่อย หรือโตไม่จำกัด บางระบบใช้ผสมกันได้ เช่น order embed item snapshot แต่ reference userId และ productId ไว้ด้วย เพื่อทั้งอ่านง่ายและยังเชื่อมกลับไปข้อมูลหลักได้

การออกแบบ MongoDB ที่ดีไม่ใช่การทำให้ schema สวยที่สุด แต่คือทำให้ query สำคัญเร็วที่สุด โดยไม่สร้างภาระตอนข้อมูลโต 🚀

แนวทางนำไปใช้

  • นำแนวคิดจากโพสต์นี้ไปทดลองกับงานจริงของคุณ
  • แยกเป็นขั้นตอนเล็ก ๆ แล้วทำทีละส่วน
  • บันทึกผลลัพธ์และสิ่งที่เรียนรู้เพื่อต่อยอด

สรุป

เลือกโครงสร้าง document จากรูปแบบการอ่าน ขนาดข้อมูล การเติบโต และความถี่ในการแก้ไข เพื่อเลี่ยงทั้ง query ซับซ้อนและ document ที่โตจนควบคุมไม่ได้