โครงการปัจจุบันของฉันคือการทำงานของระบบจัดการเอกสารโรงงาน
ที่กล่าวว่ามีริ้วรอยบางอย่าง (แปลกใจแปลกใจ) ในขณะที่รอยย่นบางอย่างมีความเฉพาะเจาะจงกับโครงการฉันเชื่อว่ามีข้อสังเกตทั่วไปและคำถามที่เกิดขึ้นซึ่งไม่มีคำตอบที่ยอมรับ (ซึ่งฉันสามารถหาได้) และที่เกี่ยวข้องกับโดเมนปัญหาที่กว้างขึ้น . มีจำนวนมากที่นี่และฉันไม่แน่ใจว่าเป็นแบบที่ดีสำหรับรูปแบบคำถามและคำตอบ StackExchange แต่ฉันคิดว่ามันเป็น) คำถามที่ตอบได้และข) ไม่เฉพาะเจาะจงมากพอที่จะเป็นประโยชน์ต่อชุมชน ข้อพิจารณาบางอย่างของฉันนั้นเฉพาะเจาะจงสำหรับฉัน แต่ฉันคิดว่าคำถามนี้อาจเป็นประโยชน์กับทุกคนที่ต้องเผชิญกับการตัดสินใจเลือก SQL กับ NoSQL เทียบกับทั้งคู่
พื้นหลัง:
แอปพลิเคชันเว็บที่เรากำลังสร้างประกอบด้วยข้อมูลที่สัมพันธ์กันอย่างชัดเจนในธรรมชาติรวมถึงข้อมูลที่มุ่งเน้นที่เอกสาร เราต้องการเค้กและกินมันด้วย
TL; DR: ฉันคิดว่า # 5 ด้านล่างผ่านการทดสอบกลิ่น คุณ ใครบ้างมีประสบการณ์กับการรวม SQL และ NOSQL ในแอปพลิเคชันเดียวหรือไม่ ฉันพยายามระบุวิธีที่เป็นไปได้ทั้งหมดสำหรับปัญหานี้ในด้านล่าง ฉันพลาดตัวเลือกที่มีแนวโน้มหรือไม่
ซับซ้อน:
- มีคลาสเอกสารที่แตกต่างกันมากมาย ข้อกำหนดนี้ต้องการเอกสารที่แตกต่างกันหลายสิบฉบับ หมายเลขนี้จะสูงขึ้นเท่านั้น กรณีที่ดีที่สุดคือกรณีที่เราสามารถใช้ภาษาเฉพาะโดเมนแบบง่ายการสร้างรหัสและสคีมาที่มีความยืดหยุ่นเพื่อให้ผู้เชี่ยวชาญด้านโดเมนสามารถจัดการกับการเพิ่มคลาสเอกสารใหม่โดยไม่ต้องมีการแทรกแซงจาก DBA หรือโปรแกรมเมอร์ (หมายเหตุ: ทราบอยู่แล้วว่าเรากำลังดำเนินการตามกฎข้อที่สิบของ Greenspun )
- ความสมบูรณ์ของการเขียนที่สำเร็จก่อนหน้านี้เป็นข้อกำหนดหลักของโครงการ ข้อมูลจะเป็นสิ่งสำคัญทางธุรกิจ ความหมายแบบเต็มกรดในการเขียนสามารถเสียสละหากสิ่งที่จะได้รับการเขียนเขียนอยู่ประสบความสำเร็จ
- เอกสารมีความซับซ้อน เอกสารต้นแบบในกรณีเฉพาะของเราจะต้องมีการจัดเก็บข้อมูลกว่า 150+ ชิ้นต่อเอกสารตัวอย่าง กรณีทางพยาธิวิทยาอาจมีลำดับความรุนแรงน้อยกว่า แต่ไม่ใช่สองอย่าง
- เอกสารชั้นเดียวเป็นเป้าหมายที่เคลื่อนที่ได้ภายใต้การอัพเดตในเวลาต่อมา
- เราชอบของฟรีที่เราได้รับจาก Django เมื่อเราเชื่อมโยงเข้ากับฐานข้อมูลเชิงสัมพันธ์ เราต้องการเก็บของฟรีไว้โดยไม่ต้องย้อนกลับสองรุ่น Django เพื่อใช้ส้อม django-nonrel การทิ้ง ORM ทั้งหมดนั้นดีกว่าที่จะลดระดับเป็น 1.3
โดยพื้นฐานแล้วมันเป็นความผิดพลาดของข้อมูลเชิงสัมพันธ์ (เช่นแอปพลิเคชันเว็บทั่วไปของคุณเช่นผู้ใช้กลุ่ม ฯลฯ รวมถึงข้อมูลเมตาของเอกสารที่เราจะต้องสามารถหั่นและลูกเต๋าด้วยการค้นหาที่ซับซ้อนแบบเรียลไทม์) และข้อมูลเอกสาร (เช่น ฟิลด์นับร้อยที่เราไม่สนใจในการเข้าร่วมหรือสอบถามโดย - กรณีการใช้งานเฉพาะของเราสำหรับข้อมูลจะใช้สำหรับการแสดงเอกสารเดียวที่มันถูกป้อน)
ฉันต้องการตรวจสอบสติ (ถ้าคุณตรวจสอบประวัติการโพสต์ของฉันฉันค่อนข้างชัดเจนเกี่ยวกับความจริงที่ว่าฉันไม่ใช่ DBA) เกี่ยวกับวิธีการที่ฉันต้องการรวมทั้งระบุตัวเลือกทั้งหมดที่ฉันเจอเพื่อการแก้ไขอื่น ๆ ปัญหาที่คล้ายกันในวงกว้างที่เกี่ยวข้องกับทั้งข้อมูลเชิงสัมพันธ์และไม่ใช่ข้อมูลเชิงสัมพันธ์
โซลูชั่นที่เสนอ:
1. หนึ่งตารางต่อคลาสเอกสาร
แต่ละคลาสเอกสารจะได้รับตารางของตัวเองพร้อมคอลัมน์สำหรับข้อมูลเมตาและข้อมูลทั้งหมด
ข้อดี:
- แบบจำลองข้อมูล SQL มาตรฐานกำลังเล่นอยู่
- จัดการข้อมูลเชิงสัมพันธ์ด้วยวิธีที่ดีที่สุด เราจะทำให้เป็นปกติในภายหลังหากเราต้องการ
- อินเทอร์เฟซผู้ดูแลระบบของ Django นั้นสะดวกสบายกับการตรวจสอบตารางเหล่านี้และ ORM สามารถใช้ชีวิตอย่างมีความสุขด้วยข้อมูล 100% นอกกรอบ
ข้อเสีย:
- การบำรุงรักษาฝันร้าย หลายสิบ (หลายร้อย) ของตารางที่มี (หลายสิบของ) คอลัมน์หลายพัน
- ตรรกะระดับแอปพลิเคชันที่รับผิดชอบในการตัดสินใจว่าจะเขียนตารางใด ทำให้ชื่อตารางเป็นพารามิเตอร์สำหรับเคียวรีที่เหม็น
- โดยทั่วไปการเปลี่ยนแปลงตรรกะทางธุรกิจทั้งหมดจะต้องมีการเปลี่ยนแปลงสคี
- กรณีทางพยาธิวิทยาอาจต้องการข้อมูลการสตริปสำหรับรูปแบบเดียวในหลายตาราง (ดู: จำนวนคอลัมน์สูงสุดในตาราง PostgreSQL คืออะไร )
- เราอาจจะต้องไปหา DBA ที่แท้จริงและซื่อสัตย์ต่อพระเจ้าซึ่งไม่ต้องสงสัยเลยว่าท้ายที่สุดจะเกลียดชีวิตและเรา
2. การสร้างแบบจำลอง EAV
มีเพียงตารางเขตข้อมูล การสร้างแบบจำลองของเอนทิตีแอตทริบิวต์ค่าเป็นที่เข้าใจกันดีอยู่แล้ว ฉันได้รวมไว้เพื่อความสมบูรณ์ ฉันไม่คิดว่าโครงการใหม่ใด ๆ ที่เริ่มต้นขึ้นในปี 2556 จะเป็นไปตามแนวทาง EAV ตามวัตถุประสงค์
ข้อดี:
- ง่ายต่อการสร้างแบบจำลอง
ข้อเสีย:
- ค้นหายากขึ้น
- เลเยอร์ DB ไม่มีการนำเสนอแบบตรงไปตรงมาสำหรับสิ่งที่ถือเป็นวัตถุระดับแอปหนึ่งอีกต่อไป
- เราจะสูญเสียการตรวจสอบข้อ จำกัด ระดับ DB
- จำนวนแถวในหนึ่งตารางจะโตเร็วขึ้น 100s-1000s อาการปวดจุดในอนาคตมีแนวโน้มที่ชาญฉลาด
- การจัดทำดัชนีมี จำกัด
- DB schema นั้นไร้ความหมายเท่าที่ ORM เกี่ยวข้อง แบตเตอรีที่รวมแอปพลิเคชันบนเว็บจะได้รับการเก็บรักษาไว้ แต่โมเดลข้อมูลที่กำหนดเองจะต้องมีการสืบค้น
3. ใช้เขตข้อมูล PostgreSQL hstore หรือ json
ฟิลด์ประเภทใดประเภทหนึ่งเหล่านี้จะทำเคล็ดลับสำหรับการจัดเก็บข้อมูลสกีมาภายในบริบทของฐานข้อมูลเชิงสัมพันธ์ เหตุผลเดียวที่ฉันไม่กระโดดเพื่อแก้ปัญหานี้ทันทีคือมันเป็นเรื่องค่อนข้างใหม่ (แนะนำในรุ่น 8.4 จึงไม่ว่าใหม่) ผมมีศูนย์เปิดรับก่อนหน้านี้กับมันและผมที่น่าสงสัย มันทำให้ฉันผิดเพราะเหตุผลเดียวกันกับที่ฉันรู้สึกไม่สบายใจที่จะโยนข้อมูลที่ดีและทำให้เป็นมาตรฐานได้อย่างง่ายดายไปยัง Mongo - แม้ว่า Mongo สามารถจัดการการอ้างอิงระหว่างเอกสารได้
ข้อดี:
- เราได้รับประโยชน์จาก Django ORM และการตรวจสอบสิทธิ์และการจัดการเซสชันในตัว
- ทุกอย่างอยู่ในแบ็กเอนด์เดียวที่เราเคยใช้กับโปรเจ็กต์อื่นสำเร็จ
ข้อเสีย:
- ไม่มีประสบการณ์กับสิ่งนี้เป็นการส่วนตัว
- มันดูไม่เหมือนคุณสมบัติที่ใช้อย่างมาก ดูเหมือนว่าพวกเขาจะได้รับการแนะนำเล็กน้อยสำหรับคนที่ดูโซลูชัน NOSQL แต่ฉันไม่เห็นหลักฐานมากมายว่าพวกเขากำลังถูกเลือก นี่ทำให้ฉันคิดว่าฉันต้องคิดถึงบางสิ่งบางอย่าง
- ค่าทั้งหมดที่เก็บไว้เป็นสตริง สูญเสียการตรวจสอบข้อ จำกัด ระดับ DB
- ข้อมูลใน hstore จะไม่ปรากฏต่อผู้ใช้เว้นแต่พวกเขาจะดูเอกสารโดยเฉพาะ แต่ข้อมูลเมตาที่เก็บไว้ในคอลัมน์มาตรฐานเพิ่มเติมจะเป็น เราจะเอาชนะเมตาดาต้านั้นขึ้นมาและฉันกังวลว่าร้านค้าขนาดใหญ่ที่เราจะสร้างนั้นอาจมาพร้อมกับข้อเสียด้านประสิทธิภาพ
4. ไปเจาะเอกสารเต็มเจาะ
ทำเอกสารทุกสิ่ง (ในความหมาย MongoDB) สร้างประเภทคอลเลกชันเดียวDocument
และเรียกมันว่าวัน นำข้อมูลอุปกรณ์ต่อพ่วงทั้งหมด (รวมถึงข้อมูลในบัญชีผู้ใช้กลุ่ม ฯลฯ ) เข้าสู่ Mongo เช่นกัน เห็นได้ชัดว่าวิธีนี้ดีกว่าแบบจำลอง EAV แต่ฉันรู้สึกผิดด้วยเหตุผลเดียวกัน # 3 รู้สึกผิด - พวกเขาทั้งคู่รู้สึกเหมือนใช้ค้อนของคุณเป็นไขควงเช่นกัน
ข้อดี:
- ไม่จำเป็นต้องโมเดลข้อมูลล่วงหน้า มีคอลเล็กชันหนึ่งชุดที่มีเอกสารประเภท
Document
และเรียกมันว่าวัน - ลักษณะการปรับขนาดที่รู้จักกันดีนั้นการรวบรวมจะต้องเติบโตเพื่อรวมเป็นล้านหรือแม้แต่เอกสารนับพันล้าน
- รูปแบบ JSON (BSON) นั้นใช้งานง่ายสำหรับนักพัฒนา
- ตามที่ฉันเข้าใจ (ซึ่งตอนนี้คลุมเครือเท่านั้น) โดยการหวาดระแวงเกี่ยวกับระดับความกังวลในการเขียนแม้กระทั่งอินสแตนซ์เดียวก็สามารถให้ความปลอดภัยของข้อมูลที่แข็งแกร่งมากในกรณีที่มีสิ่งใด ๆ
ข้อเสีย:
- ORM ออกไปนอกหน้าต่างสำหรับ Django trunk ของแจกฟรีที่ออกไปนอกหน้าต่างด้วย: กรอบการตรวจสอบ, กรอบเซสชัน, ส่วนต่อประสานผู้ดูแลระบบ, สิ่งอื่น ๆ อีกมากมายแน่นอน
- จะต้องใช้ความสามารถในการอ้างอิงของ Mongo (ซึ่งต้องใช้หลายแบบสอบถาม) หรือลบข้อมูล ไม่เพียง แต่เราจะสูญเสียของฟรีที่เราได้รับจาก Django เท่านั้นเรายังสูญเสียของฟรีเช่น JOIN ที่เราได้รับจาก PostgreSQL
- ความปลอดภัยของข้อมูล เมื่อมีคนอ่านเกี่ยวกับ MongoDB ดูเหมือนว่ามีอย่างน้อยหนึ่งคนที่อ้างถึงว่ามันจะทำให้ข้อมูลของคุณสูญหาย พวกเขาไม่เคยอ้างถึงเหตุการณ์ที่เกิดขึ้นโดยเฉพาะและมันอาจจะเป็นแค่ hogwash หรือเพียงแค่เกี่ยวข้องกับไฟเริ่มต้นเก่าและลืมความกังวลในการเขียน แต่มันก็ยังเป็นกังวลฉัน แน่นอนว่าเราจะใช้กลยุทธ์การสำรองข้อมูลหวาดระแวงอย่างยุติธรรมในทุกกรณี (หากข้อมูลเสียหายอย่างเงียบ ๆ ซึ่งอาจเป็นสาระสำคัญอย่างแน่นอน .. )
5. PostgreSQL และ MongoDB
ข้อมูลเชิงสัมพันธ์ไปในฐานข้อมูลเชิงสัมพันธ์และข้อมูลเอกสารจะอยู่ในฐานข้อมูลเชิงเอกสาร documents
ตารางในฐานข้อมูลเชิงสัมพันธ์มีทั้งหมดของข้อมูลที่เราอาจจำเป็นต้องดัชนีหรือฝานและลูกเต๋าบนเช่นเดียวกับ MongoDB มี objectid ซึ่งเราจะใช้เมื่อเราต้องการที่จะแบบสอบถามสำหรับค่าที่แท้จริงของเขตข้อมูลในเอกสาร เราจะไม่สามารถใช้ ORM หรือผู้ดูแลระบบในตัวสำหรับค่าของเอกสารด้วยตัวเอง แต่นั่นไม่ใช่การสูญเสียครั้งใหญ่เนื่องจากแอปทั้งหมดนั้นเป็นอินเทอร์เฟซผู้ดูแลระบบสำหรับเอกสารและเราน่าจะต้อง ปรับแต่งส่วนเฉพาะของ ORM ให้เป็นระดับที่ยอมรับไม่ได้เพื่อให้มันทำงานตามที่เราต้องการ
ข้อดี:
- แต่ละแบ็กเอนด์ทำในสิ่งที่ดี
- การอ้างอิงระหว่างโมเดลถูกเก็บรักษาไว้โดยไม่ต้องใช้หลายเคียวรี
- เราได้เก็บแบตเตอรี่ Django ไว้เท่าที่ผู้ใช้งานและอื่น ๆ กังวล
- ต้องการเพียงหนึ่ง
documents
ตารางเท่านั้นไม่ว่าจะสร้างเอกสารประเภทต่าง ๆ จำนวนเท่าใด - ข้อมูลเอกสารที่มีการสืบค้นน้อยมักถูกแยกออกจากเมตาดาต้าที่มีการสอบถามบ่อยๆ
ข้อเสีย:
- การดึงข้อมูลเอกสารจะต้องมีการสืบค้นตามลำดับ 2 ครั้งแรกเทียบกับ SQL DB แล้วเทียบกับ MongoDB (แม้ว่าจะไม่เลวร้ายไปกว่านั้นหากข้อมูลเดียวกันถูกเก็บไว้ใน Mongo และไม่ทำให้เสียสภาพ)
- การเขียนจะไม่เป็นอะตอมอีกต่อไป การเขียนกับเอกสาร Mongo เดียวนั้นรับประกันว่าเป็นอะตอมและ PG เห็นได้ชัดว่าสามารถรับประกันอะตอมมิกซิตี้ แต่การประกันว่าอะตอมมิกของการเขียนในทั้งสองจะต้องใช้ตรรกะแอปพลิเคชันไม่ต้องสงสัยเลยว่าประสิทธิภาพและความซับซ้อน
- สองแบ็กเอนด์ = สองเคียวรีภาษา = สองโปรแกรมที่แตกต่างกันที่มีข้อกำหนดของผู้ดูแลระบบที่แตกต่างกัน = สองฐานข้อมูลที่แย่งหน่วยความจำ
JSON
ประเภทข้อมูล อย่ากลัวที่จะใช้คุณสมบัติใหม่ใน Postgres ทีมงาน Postgres จะไม่ปล่อยคุณลักษณะที่ไม่เสถียร และ 9.2 ไม่ใช่สิ่งใหม่จริง) นอกจากนี้คุณสามารถใช้ประโยชน์จากคุณสมบัติ JSON ใหม่ใน 9.3 เมื่อมี หากคุณกำลังประมวลผลเอกสารในรหัสแอปพลิเคชันของคุณ (แทนที่จะใช้ SQL) คุณสามารถเก็บ JSON ไว้ในtext
คอลัมน์ปกติได้