MongoDB Schema Design - เอกสารขนาดเล็กจำนวนมากหรือเอกสารขนาดใหญ่น้อยกว่า?


89

ความเป็นมา
ฉันกำลังสร้างต้นแบบการแปลงจากฐานข้อมูล RDBMS ของเราเป็น MongoDB ในขณะที่การทำให้เป็นปกติดูเหมือนว่าฉันมีสองทางเลือกทางเลือกหนึ่งซึ่งนำไปสู่เอกสารขนาดเล็กจำนวนมาก (หลายล้าน) หรืออีกทางหนึ่งซึ่งนำไปสู่เอกสารขนาดใหญ่น้อยลง (หลายแสน)

ถ้าฉันสามารถกลั่นมันให้เป็นอะนาล็อกธรรมดาได้ก็จะมีความแตกต่างระหว่างคอลเล็กชันที่มีเอกสารของลูกค้าน้อยกว่าเช่นนี้ (ใน Java):

คลาสลูกค้า {
    ชื่อสตริงส่วนตัว
    ที่อยู่ส่วนตัว
    // CreditCard แต่ละรายการมีอินสแตนซ์การชำระเงินหลายร้อยรายการ
    ชุดส่วนตัว <CreditCard> creditCards;
}

หรือคอลเลกชันที่มีเอกสารการชำระเงินจำนวนมากเช่นนี้:

class Payment {
    ลูกค้าลูกค้าส่วนตัว
    CreditCard ส่วนตัว creditCard;
    วันที่ส่วนตัว payDate;
    ส่วนตัวลอย payAmount;
}

คำถาม
MongoDB ออกแบบมาเพื่อรองรับเอกสารขนาดเล็กจำนวนมากหรือเอกสารขนาดใหญ่น้อยกว่าหรือไม่? คำตอบส่วนใหญ่ขึ้นอยู่กับคำถามที่ฉันวางแผนจะเรียกใช้หรือไม่? (เช่นลูกค้า X มีบัตรเครดิตกี่ใบเทียบกับจำนวนเงินเฉลี่ยที่ลูกค้าจ่ายทั้งหมดในเดือนที่แล้ว?)

ฉันมองไปรอบ ๆ มากมาย แต่ฉันไม่ได้สะดุดกับแนวทางปฏิบัติที่ดีที่สุดของ MongoDB schema ที่จะช่วยฉันตอบคำถามของฉัน

คำตอบ:


82

คุณจะต้องเพิ่มประสิทธิภาพอย่างแน่นอนสำหรับคำถามที่คุณกำลังทำอยู่

นี่คือการคาดเดาที่ดีที่สุดของฉันตามคำอธิบายของคุณ

คุณอาจต้องการทราบบัตรเครดิตทั้งหมดสำหรับลูกค้าแต่ละรายดังนั้นโปรดเก็บบัตรเหล่านั้นไว้ใน Customer Object นอกจากนี้คุณอาจต้องการข้อมูลอ้างอิงของลูกค้าสำหรับการชำระเงินแต่ละครั้ง วิธีนี้จะทำให้เอกสารการชำระเงินค่อนข้างเล็ก

ออบเจ็กต์การชำระเงินจะมี ID และดัชนีของตัวเองโดยอัตโนมัติ คุณอาจต้องการเพิ่มดัชนีในการอ้างอิงลูกค้าด้วย

วิธีนี้จะช่วยให้คุณค้นหาการชำระเงินโดยลูกค้าได้อย่างรวดเร็วโดยไม่ต้องจัดเก็บวัตถุของลูกค้าทั้งหมดทุกครั้ง

หากคุณต้องการตอบคำถามเช่น"จำนวนเงินเฉลี่ยที่ลูกค้าทั้งหมดจ่ายในเดือนที่แล้วคือเท่าใด"คุณจะต้องใช้แผนที่ / ลดขนาดชุดข้อมูลขนาดใดก็ได้ คุณไม่ได้รับคำตอบนี้แบบ "เรียลไทม์" คุณจะพบว่าการจัดเก็บ "ข้อมูลอ้างอิง" ถึงลูกค้านั้นดีพอสำหรับการลดแผนที่เหล่านี้

เพื่อตอบคำถามของคุณโดยตรง: MongoDB ออกแบบมาเพื่อให้ชอบเอกสารขนาดเล็กจำนวนมากหรือเอกสารขนาดใหญ่น้อยกว่าหรือไม่?

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


32

ตามเอกสารของ MongoDB ดูเหมือนว่าออกแบบมาสำหรับเอกสารขนาดเล็กจำนวนมาก

จากแนวทางปฏิบัติที่ดีที่สุดด้านประสิทธิภาพสำหรับ MongoDB :

ขนาดสูงสุดสำหรับเอกสารใน MongoDB คือ 16 MB ในทางปฏิบัติเอกสารส่วนใหญ่มีขนาดไม่กี่กิโลไบต์หรือน้อยกว่า พิจารณาเอกสารเหมือนแถวในตารางมากกว่าตาราง แทนที่จะเก็บรักษารายการบันทึกไว้ในเอกสารเดียวให้ทำบันทึกแต่ละรายการแทน

จากกฎ 6 ข้อสำหรับการออกแบบ MongoDB Schema: ตอนที่ 1 :

การสร้างแบบจำลองแบบตัวต่อตัว

ตัวอย่างของ“ หนึ่งต่อสองสาม” อาจเป็นที่อยู่ของบุคคล นี่เป็นกรณีการใช้งานที่ดีสำหรับการฝัง - คุณต้องใส่ที่อยู่ในอาร์เรย์ภายในวัตถุบุคคลของคุณ

หนึ่งต่อหลาย

ตัวอย่างของ "หนึ่งต่อหลาย" อาจเป็นชิ้นส่วนของผลิตภัณฑ์ในระบบการสั่งซื้อชิ้นส่วนทดแทน ผลิตภัณฑ์แต่ละชิ้นอาจมีชิ้นส่วนอะไหล่ทดแทนได้มากถึงหลายร้อยชิ้น แต่ไม่เกินสองหมื่นชิ้นหรือมากกว่านั้น นี่เป็นกรณีการใช้งานที่ดีสำหรับการอ้างอิง - คุณต้องใส่ ObjectIDs ของชิ้นส่วนในอาร์เรย์ในเอกสารผลิตภัณฑ์

หนึ่งต่อ Squillions

ตัวอย่างของ“ one-to-squillions” อาจเป็นระบบบันทึกเหตุการณ์ที่รวบรวมข้อความบันทึกสำหรับเครื่องต่างๆ โฮสต์ใด ๆ ที่ระบุสามารถสร้างข้อความได้มากพอที่จะทำให้ขนาดเอกสารเกิน 16 MB แม้ว่าทั้งหมดที่คุณเก็บไว้ในอาร์เรย์คือ ObjectID นี่เป็นกรณีการใช้งานแบบคลาสสิกสำหรับ "การอ้างอิงผู้ปกครอง" - คุณจะมีเอกสารสำหรับโฮสต์จากนั้นเก็บ ObjectID ของโฮสต์ไว้ในเอกสารสำหรับข้อความบันทึก


13

เอกสารที่เติบโตขึ้นอย่างมากเมื่อเวลาผ่านไปอาจเป็นการระเบิดเวลา แบนด์วิดท์เครือข่ายและการใช้ RAM อาจกลายเป็นปัญหาคอขวดที่วัดได้ทำให้คุณต้องเริ่มต้นใหม่

ขั้นแรกให้พิจารณาสองคอลเลกชัน: ลูกค้าและการชำระเงิน ดังนั้นเมล็ดข้าวจึงค่อนข้างเล็ก: หนึ่งเอกสารต่อการชำระเงิน

ถัดไปคุณต้องตัดสินใจว่าจะสร้างแบบจำลองข้อมูลบัญชีอย่างไรเช่นบัตรเครดิต ลองพิจารณาว่าเอกสารของลูกค้ามีอาร์เรย์ของข้อมูลบัญชีหรือไม่หรือคุณต้องการการรวบรวมบัญชีใหม่

หากเอกสารบัญชีแยกจากเอกสารของลูกค้าการโหลดบัญชีทั้งหมดสำหรับลูกค้ารายหนึ่งลงในหน่วยความจำจำเป็นต้องดึงเอกสารหลายชุด ซึ่งอาจแปลเป็นหน่วยความจำพิเศษ I / O แบนด์วิดท์และการใช้งาน CPU นั่นหมายความว่าการรวบรวมบัญชีเป็นความคิดที่ไม่ดีในทันทีหรือไม่?

การตัดสินใจของคุณมีผลต่อเอกสารการชำระเงิน หากข้อมูลบัญชีฝังอยู่ในเอกสารของลูกค้าคุณจะอ้างอิงอย่างไร เอกสารบัญชีแยกกันมีแอตทริบิวต์ _id ของตนเอง ด้วยข้อมูลบัญชีที่ฝังไว้แอปพลิเคชันของคุณอาจสร้างรหัสใหม่สำหรับบัญชีหรือใช้แอตทริบิวต์ของบัญชี (เช่นหมายเลขบัญชี) สำหรับคีย์

เอกสารการชำระเงินสามารถมีการชำระเงินทั้งหมดในกรอบเวลาที่กำหนดได้จริงหรือไม่ (เช่นวัน?) ความซับซ้อนดังกล่าวจะส่งผลต่อรหัสทั้งหมดที่อ่านและเขียนเอกสารการชำระเงิน การเพิ่มประสิทธิภาพก่อนกำหนดอาจเป็นอันตรายต่อโครงการได้

เช่นเดียวกับเอกสารบัญชีการชำระเงินสามารถอ้างอิงได้อย่างง่ายดายตราบใดที่เอกสารการชำระเงินมีการชำระเงินเพียงครั้งเดียว เอกสารประเภทใหม่เช่นเครดิตสามารถอ้างอิงการชำระเงิน แต่คุณจะสร้างคอลเลกชันเครดิตหรือคุณจะฝังข้อมูลเครดิตไว้ในข้อมูลการชำระเงิน? จะเกิดอะไรขึ้นหากคุณต้องการอ้างอิงเครดิตในภายหลัง

สรุปได้ว่าฉันประสบความสำเร็จกับเอกสารขนาดเล็กจำนวนมากและคอลเล็กชันมากมาย ฉันใช้การอ้างอิงด้วย _id และเฉพาะกับ _id ดังนั้นฉันไม่ต้องกังวลว่าเอกสารที่เพิ่มขึ้นเรื่อย ๆ จะทำลายใบสมัครของฉัน สคีมาเข้าใจง่ายและจัดทำดัชนีเนื่องจากแต่ละเอนทิตีมีคอลเล็กชันของตนเอง เอนทิตีที่สำคัญไม่ได้ซ่อนอยู่ในเอกสารอื่น ๆ

ฉันชอบที่จะได้ยินเกี่ยวกับสิ่งที่คุณค้นพบ โชคดี!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.