เป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ที่จะมีความสัมพันธ์แบบหนึ่งต่อหนึ่งที่ไม่เหมือนใคร


38

Say โต๊ะcarมีความสัมพันธ์แบบหนึ่งต่อหนึ่งตารางelectric_car, และgas_car hybrid_carหาก a carคือelectric_carมันไม่สามารถปรากฏในgas_carหรืออีกต่อไปhybrid_carฯลฯ

มีอะไรผิดปกติกับการออกแบบเช่นนี้หรือไม่? ปัญหาบางอย่างที่อาจเกิดขึ้นตามท้องถนน?

คำตอบ:


59

รถยนต์ประเภทต่าง ๆ เป็นตัวอย่างของปัญหาทั่วไปที่พบบ่อยครั้งในการสร้างแบบจำลองข้อมูล มันถูกเรียกว่า "generalization / specialization" ในการสร้างแบบจำลอง ER และ "superclass / subclass" ในการสร้างแบบจำลองวัตถุ

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

ผู้สร้างแบบจำลองเชิงสัมพันธ์ต้องเผชิญกับปัญหา วิธีการออกแบบตารางเพื่อเลียนแบบประโยชน์ที่จะได้รับจากการสืบทอด?

เทคนิคที่ง่ายที่สุดที่เรียกว่ามรดกตารางเดียว ข้อมูลเกี่ยวกับรถยนต์ทุกประเภทจัดกลุ่มเป็นตารางเดียวสำหรับรถยนต์ มีคอลัมน์คือ car_type ที่จัดกลุ่มรถยนต์ทุกประเภทเข้าด้วยกัน ไม่มีรถยนต์ใดที่สามารถเป็นของมากกว่าหนึ่งประเภท หากคอลัมน์ไม่เกี่ยวข้องกับการพูดรถยนต์ไฟฟ้าก็จะถูกปล่อยให้เป็นโมฆะในแถวที่เกี่ยวข้องกับรถยนต์ไฟฟ้า

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

มีเทคนิคที่เรียกว่าเป็นมรดกโต๊ะระดับ ในการออกแบบนี้มีตารางแยกต่างหากสำหรับ gas_car, electric_car และ hybrid_car นอกเหนือจากตารางรวมรถยนต์สำหรับพวกเขาทั้งหมด เมื่อคุณต้องการข้อมูลทั้งหมดเกี่ยวกับรถยนต์ประเภทใดประเภทหนึ่งคุณสามารถเข้าร่วมตารางรถด้วยตารางเฉพาะที่เหมาะสม มี NULL น้อยลงในการออกแบบนี้ แต่คุณเข้าร่วมได้มากขึ้น เทคนิคนี้ทำงานได้ดีขึ้นในกรณีที่มีขนาดใหญ่และซับซ้อนมากขึ้น

มีเทคนิคที่สามที่เรียกว่าคีย์หลักที่ใช้ร่วมกัน เทคนิคนี้มักใช้ร่วมกับการสืบทอดตารางคลาส ตารางพิเศษสำหรับคลาสย่อยมีสำเนาของคีย์หลักของรายการที่เกี่ยวข้องในตารางรถยนต์ คอลัมน์รหัสนี้สามารถประกาศให้เป็นทั้งคีย์หลักและคีย์ต่างประเทศ

สิ่งนี้เกี่ยวข้องกับการเขียนโปรแกรมเพิ่มเติมเล็กน้อยเมื่อมีการเพิ่มรถยนต์ใหม่ แต่จะทำให้การเข้าร่วมนั้นง่ายง่ายและรวดเร็ว

ซูเปอร์คลาสและคลาสย่อยเกิดขึ้นตลอดเวลาในโลกแห่งความเป็นจริง อย่ากลัว แต่ทดสอบการออกแบบเบื้องต้นเพื่อประสิทธิภาพ หากความพยายามครั้งแรกของคุณเรียบง่ายและมีเสียงคุณจะสามารถปรับแต่งมันเพื่อเร่งความเร็ว


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

6
คำตอบที่ยอดเยี่ยมที่นี่ หนึ่งคำแนะนำ: บันทึกการตัดสินใจออกแบบเหล่านี้อย่างละเอียด ไม่ว่าเส้นทางที่คุณไปนั้นจะไม่ชัดเจนเมื่อมีใครตรวจสอบโครงสร้างฐานข้อมูล ฐานข้อมูลบางอย่างเช่นPostgres ช่วยให้คุณสามารถผูกความคิดเห็นพร้อมกับ meta-data ของคอลัมน์ตารางและอื่น ๆ
Basil Bourque

คุณไม่ได้ จำกัด การควบคุมรถยนต์ไฟฟ้าไม่ให้เป็นรถยนต์ไฮบริด คุณต้องการตารางแยกต่างหากสำหรับสิ่งนั้น
jmoreno

2
คุณพูดถูก หากคุณเพิ่มฟิลด์ car_type ลงในตารางรถยนต์คุณสามารถ จำกัด รถยนต์ให้เป็นของประเภทเดียวเท่านั้นโดยมีค่าใช้จ่ายในการเบี่ยงเบนจากการปรับสภาพแบบเต็ม DBMS ที่ดีจะช่วยให้คุณกำหนดข้อ จำกัด การตรวจสอบที่จะป้องกันไม่ให้รถเข้าไปในตารางพิเศษมากกว่าหนึ่งตาราง มีค่าใช้จ่ายในการที่คุณไปเพิ่มรถใหม่
วอลเตอร์ Mitty

@WalterMitty แต่ไม่มีcar_typeฟิลด์คุณจะทราบได้อย่างไรว่าจะค้นหารายละเอียดใดเมื่อดึงข้อมูล คุณต้องอ่านทั้งสามตารางเพื่อดูว่าตารางใดมีข้อมูลเกี่ยวกับcarบันทึกเฉพาะนั้นหรือไม่
Josh Part

12

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

ตัวอย่างเช่นภายใต้ตัวอย่างของคุณคุณทำอะไรกับ Audi A4 eTron ซึ่งเป็นปลั๊กอินไฮบริด นั่นคือ "รถยนต์ไฟฟ้า" หรือเป็น "รถยนต์ไฮบริด" หรือไม่?

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

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

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


ขอบคุณฉันกลัวว่าฉันจะวางกับดักสำหรับตัวเอง ปัญหาของฉันคือแต่ละชนิดย่อยจะมีคอลัมน์จำนวนมาก บางคนจะซ้อนทับกันและฉันจะวางพวกเขาในcarตาราง แต่หลายคนจะไม่ได้และจะถูกวางไว้ในตารางย่อย ตัวอย่างเช่นมันจะเป็นสิ่งที่ต้องการเก็บชิ้นส่วนระดับประถมของประเภทรถ เครื่องยนต์รถยนต์ไฟฟ้าสามารถมีได้ 100 ส่วนเครื่องยนต์แก๊สรถยนต์ 75 ชิ้นและไฮบริด 125 ชิ้น 50 ส่วนจะร่วมกันและเก็บไว้ในcarsขณะที่ 50, 25, และ 75 จะอยู่ในelectric_car, gas_carและhybrid_carตาราง
อาร์เธอร์ Tarasov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.