นี่เป็นวิธีที่ไร้สาระในการสร้างโครงสร้าง DB หรือไม่หรือฉันขาดอะไรไปเลย?


61

ฉันทำงานกับฐานข้อมูลเชิงสัมพันธ์และคิดว่าฉันเข้าใจแนวคิดพื้นฐานของการออกแบบสคีมาที่ดีพอสมควร ฉันเพิ่งได้รับมอบหมายให้ทำโครงการที่ DB ออกแบบโดยที่ปรึกษาที่ได้รับค่าตอบแทนสูง โปรดแจ้งให้เราทราบว่าลำไส้ของฉัน - "WTF ??!?" - ได้รับการรับประกันหรือเป็นชายผู้นี้ที่เป็นอัจฉริยะที่เขาใช้งานนอกโลกของฉันหรือไม่?

DB ในคำถามคือแอปที่ใช้ในการป้อนคำขอจากพนักงาน เพียงดูที่ส่วนเล็ก ๆ ของมันคุณมีข้อมูลเกี่ยวกับผู้ใช้และข้อมูลเกี่ยวกับการร้องขอ ฉันจะออกแบบเช่นนี้เพื่อ:

ตารางผู้ใช้:

UserID (primary Key, indexed, no dupes)
FirstName
LastName
Department

ขอโต๊ะ

RequestID (primary Key, indexed, no dupes)
<...> various data fields containing request details
UserID -- foreign key associated with User table

ง่ายใช่มั้ย

ที่ปรึกษาออกแบบแบบนี้ (พร้อมข้อมูลตัวอย่าง):

UsersTable

UserID  FirstName   LastName
234     John        Doe
516     Jane        Doe
123     Foo         Bar

DepartmentsTable

DepartmentID   Name
1              Sales
2              HR
3              IT

UserDepartmentTable

UserDepartmentID   UserID   Department
1                  234      2
2                  516      2
3                  123      1

RequestTable

RequestID   UserID   <...>
1           516      blah
2           516      blah
3           234      blah

ฐานข้อมูลทั้งหมดถูกสร้างขึ้นเช่นนี้โดยทุกชิ้นส่วนของข้อมูลถูกห่อหุ้มในตารางของตัวเองโดยมี ID ตัวเลขที่เชื่อมโยงทุกอย่างเข้าด้วยกัน เห็นได้ชัดว่าที่ปรึกษาได้อ่านเกี่ยวกับ OLAP และต้องการ 'ความเร็วในการค้นหาจำนวนเต็ม'

นอกจากนี้เขายังมีกระบวนงานที่เก็บไว้จำนวนมากเพื่ออ้างอิงข้ามตารางทั้งหมดเหล่านี้

นี่เป็นการออกแบบที่ถูกต้องสำหรับ SQL DB ขนาดเล็กถึงขนาดกลางหรือไม่?

ขอบคุณสำหรับความคิดเห็น / คำตอบ ...


12
โอ้ถ้านี่ทำให้คุณพูด WTF คุณคงไม่เห็นตารางที่มีคอลัมน์มากกว่า 200 คอลัมน์และกระบวนงานที่เก็บไว้ยาวกว่า 1,000 บรรทัด
งาน

42
+1 สำหรับการไม่ลบหลังจากรู้สึกอับอาย ขอบคุณที่ออกจากที่นี่เพื่อคนอื่นสามารถเรียนรู้
Wayne Koorts

2
@ งาน - ที่จริงฉันไม่ได้ - ฉันไม่ได้เป็น DBA โดยการค้า (ตอนนี้ค่อนข้างชัดเจนแล้ว! lol) ดังนั้นเกณฑ์ SQL WTF ของฉันจึงค่อนข้างต่ำ ถึงแม้ว่าจุดขาดของการออกแบบของที่ปรึกษาจะทำให้ฉันมีความสามารถของตัวเอง WTF เคยมีวันที่คุณรู้สึกว่าเป็นคนโง่หรือไม่?
จิม

9
@ Jim: ขอแสดงความยินดีที่คุณได้เปิดใบ้วันเป็นพุทธะวัน
Wayne Koorts

3
สาปแช่งที่ปรึกษาที่ได้ค่าตอบแทนสูง!
davidsleeps

คำตอบ:


73

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


คำตอบของคุณเหมาะสมและมองคำถามของฉันและสคีมามันอาจจะเป็นแค่จำนวนของตารางที่เขาใช้ซึ่งทำให้ฉันสับสน ฉันทำให้ตัวอย่างคำถามของฉันง่ายขึ้นอย่างมาก แต่ฉันเห็นว่าแนวคิดดังกล่าวเป็นอย่างไร - เขาแยกสิ่งต่าง ๆ ออกจากกันมากกว่าที่ฉันต้องการ เฮ้อฉันคิดว่ามันดีนะที่ฉันไม่ใช่ DBA! :)
จิม

เรียนรู้การออกแบบตามกฎสิบนาที: "สิ่งที่เป็นจริงในตอนนี้อาจจะไม่เกิดขึ้นในสิบนาที" ตรวจสอบให้แน่ใจการออกแบบของคุณสามารถจัดการกับการเปลี่ยนแปลง
Blrfl

1
สคีมานี้จริง ๆ แล้วมีข้อดีที่เมื่อมีการแทรกพนักงานแผนกของพวกเขาจะต้องมีอยู่
Simon Richter

@SimonRichter: มันไม่เป็นความจริง พนักงานสามารถสร้างโดยไม่มีแผนกใด ๆ ที่มีอยู่และยังย้อนกลับ
Daniel Dinnyes

@SimonRichter ประโยชน์ของการออกแบบนี้คือประการแรกที่กรมเป็นหน่วยงานที่แยกต่างหากและประการที่สองมีความสัมพันธ์แบบกลุ่มต่อกลุ่มระหว่างพนักงานกับพนักงานซึ่งตรงกันข้ามกับตัวอย่างของ OP ซึ่งมันเป็น "มาก - หนึ่งต่อหนึ่ง "(ไม่สามารถพูดหลายต่อหนึ่งได้เนื่องจากไม่มีแผนกเอนทิตีแยกต่างหากที่อ้างถึงถูกเรียกว่าความสัมพันธ์)
Daniel Dinnyes

48

ฉันไม่คิดว่า WTF นั้นจะได้รับการรับประกันหรือคนที่แต่งตัวประหลาดทำตัวเป็นนักออกแบบอัจฉริยะ - มันเป็นฐานข้อมูลมาตรฐานที่ค่อนข้างธรรมดา

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

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

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

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

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

LATER EDIT - อีกเหตุผลหนึ่งที่ผู้ให้คำปรึกษาอาจต้องการเพิ่มตารางตัวกลางเหล่านั้นได้รับการแก้ไขในคำถามติดตามนี้คำตอบที่ให้เหตุผลบางประการว่าทำไมการปรับโครงสร้างฐานข้อมูลใหม่มักจะยากกว่าการสร้างรหัสใหม่ซึ่งจะทำให้คุณ วิธีการ "ใส่ในตารางทั้งหมดที่คุณอาจต้องการ"


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

5
ดังที่คุณเห็นได้จากความคิดเห็นมากมายมีความสงสัยเกี่ยวกับ "ความคิดเห็น" จะมีเพียงหนึ่ง X ต่อ Y เท่านั้น " ผู้ให้คำปรึกษาปิดบังตัวเองจากการร้องเรียนว่า "ทำไมถึงมีเพียงหนึ่ง X ต่อ Y เท่านั้น" บางอย่างอาจจะเกิดขึ้น แต่เขาจะไม่รับผิดชอบในการรักษารหัสที่มีการเชื่อมต่อจำนวนมาก (ไม่เลวร้ายเกินไป แต่ยากกว่า) และต้องแก้ไขกฎธุรกิจที่ยังไม่มีอยู่ (ไม่ดี) - จินตนาการคำถาม "ทำไมผู้ใช้ถึงได้ทั้งหมด สิทธิ์จากแต่ละแผนกพวกเขาควรได้รับสิทธิ์ต่ำสุดของแต่ละสิทธิ์ "หรือบางอย่าง
psr

@psr ฉันคิดว่ามีคำที่พิมพ์ผิด: ไม่ควร "คำค้นหาที่คิดว่ามีผู้ใช้เพียงคนเดียวต่อแผนก" เป็น "คำค้นหาที่ถือว่าผู้ใช้อยู่ในแผนกเดียว" หรือไม่
BiAiB

@BiAiB - ถูกต้องนั่นคือสิ่งที่ฉันตั้งใจจะพูด
psr

14

หากความต้องการคือมีหลายแผนกต่อผู้ใช้การออกแบบนี้สมเหตุสมผล สิ่งเดียวที่เกี่ยวกับมันคือการUserDepartmentTableมีกุญแจตัวแทนUserDepartmentIDที่ไม่ต้องการ (เพียงแค่สร้างUserIdและDepartmentIdคีย์หลักแบบคอมโพสิต)

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


18
... จนกว่าจะมีมากกว่าหนึ่งแผนกเป็นไปได้ต่อผู้ใช้หนึ่งราย
Blrfl

1
ตรง @Blrfl วันนี้ที่ไม่เคยเกิดขึ้นคือวันพรุ่งนี้ซีอีโอคือการมี aneurysm เพราะมันไม่ได้ทำ
Adam Crossland

2
ส่วนหนึ่งของการตัดสินใจว่าอะไรที่ควรค่าแก่การบำบัดประเภทนี้คือการเข้าใจถึงปัญหา ในบางแอปพลิเคชั่นอาจเป็นสิ่งสำคัญที่จะต้องรู้ว่าพนักงาน # 3804 เป็นที่รู้จักของ บริษัท ในชื่อแอนสมิ ธ และแอนโจนส์ (หลังจากแต่งงานแล้ว) ซึ่งจะทำให้ชื่อของพนักงานเป็นเรื่องปกติ ในกรณีของจิมมันอาจคุ้มค่าที่จะขยายตารางเบรกเกอร์เพื่อเก็บประวัติเพื่อที่ว่าหากแอนย้ายจากฝ่ายทรัพยากรบุคคลไปสู่ไอทีความจริงที่ว่าคำขอเก่าที่เชื่อมโยงกับเธออาจสะท้อนให้เห็นว่ามันเป็นคำขอของฝ่ายทรัพยากรบุคคล
Blrfl

8
YAGNI - ฐานข้อมูลสามารถ refactored
JeffO

2
@Oded ผู้แมป ORM บางตัวเช่น Entity Framework ทำงานได้ไม่ดีกับตารางที่มีคีย์หลักผสม
maple_shaft

5

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

0- ความแตกต่างระหว่างผู้ใช้และพนักงานคืออะไร?

1 สมมติว่าพนักงาน = ผู้ใช้จะเกิดอะไรขึ้นถ้าพนักงานเปลี่ยนแผนก?

2-Group สามารถส่งคำขอได้ 1 ครั้งหรือไม่

3- พนักงานเป็นของแผนกมากกว่าหนึ่งได้หรือไม่ เกี่ยวกับ CEO

4- มีพนักงานบางส่วนที่ได้รับอนุญาตให้ทำการร้องขอหรือไม่?

5- จะเกิดอะไรขึ้นกับคำร้องขอเมื่อมีการลบข้อมูลพนักงาน (ถ้าเคย)

6- คุณสามารถลบคำขอได้หรือไม่? จะเกิดอะไรขึ้นเมื่อคำขอถูกลบ (ให้แน่ใจว่าคุณไม่ได้ลบบันทึกพนักงานโดย RI)

7- พนักงานสามารถทำการร้องขอ "เดียวกัน" ได้มากกว่าหนึ่งครั้ง (กำหนด "เดียวกัน")

8- วิธีจัดการกับคำร้องขอของพนักงานเมื่อพวกเขาออกจาก บริษัท (ยกเลิกคำร้องขอหรือลบคำร้องขอ?)

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


+1 เหล่านี้เป็นคำถามที่ดีที่ต้องมีการชี้แจงก่อนที่จะออกแบบสคีมาประเภทนี้ ฉันชอบการไหลของตรรกะของคุณ

@ Surfer513: ฉันขอขอบคุณความคิดเห็นที่ดีของคุณ
NoChance

1

ฉันต้องการเพิ่มบันทึกย่อในแบบฟอร์มคู่พูดคุยอย่างชัดเจนเกี่ยวกับข้อดีที่เป็นไปได้บางประการของการใช้ตารางการเข้าร่วมในแบบที่ บริษัท ที่ปรึกษาที่ได้รับค่าจ้างสูงของคุณทำ

  • จัดทำดัชนีอย่างถูกต้อง (เช่นหาก UserDepartmentTable ดัชนีสองคีย์ต่างประเทศ) มีเพียงเล็กน้อยประสิทธิภาพการสูญเสียของตารางเข้าร่วมเช่นนี้เนื่องจากกุญแจต่างประเทศไม่ได้เป็นเอกลักษณ์ หากคีย์ต่างประเทศรับประกันว่าจะไม่ซ้ำกันโดยทฤษฎีฐานข้อมูลเล็ก ๆ ที่ฉันรู้ว่าการค้นหาUserDepartmentTable.Departmentไม่ "ยาก" กว่าการค้นหาคอลัมน์อื่น ๆ ในUserตาราง
  • ตารางเข้าร่วมจะช่วยให้คุณมีความยืดหยุ่นมากขึ้นในการตั้งค่าข้อมูลอื่น ๆ เกี่ยวกับการเชื่อมโยงระหว่างผู้ใช้และแผนก (เช่นการประทับเวลาในการสร้าง)
  • ตารางการเข้าร่วมช่วยให้คุณสามารถ "เชื่อมโยง" เวอร์ชันได้อย่างง่ายดาย (เช่นเมื่อผู้ใช้เปลี่ยนแผนกให้ทริกเกอร์แฟล็กบูลีนดัชนีบางรายการUserDepartmentTable.Activeเป็นเท็จและสร้างการเชื่อมโยงใหม่ที่ใช้งานอยู่) นอกจากนี้ยังเป็นไปได้ที่จะมีการกำหนดความสัมพันธ์ของแผนกด้วยโมเดลสองตาราง (เฉพาะผู้ใช้และแผนก) แต่มันยากขึ้นและจำเป็นต้องเพิ่มคอลัมน์อย่างน้อยหนึ่งคอลัมน์หรือทำกายกรรมฐานข้อมูลเพื่อหลีกเลี่ยงการทำซ้ำคีย์หลัก
  • ช่วยให้คุณสามารถกำหนดความสัมพันธ์แบบหนึ่งต่อหลายหรือหลายกลุ่มหรือหลายกลุ่มได้อย่างง่ายดาย

ที่ถูกกล่าวว่ามีเหตุผลหลายประการที่จะไม่ทำในสิ่งที่ที่ปรึกษาจ่ายสูงของคุณทำ

  • ทั้งหมดข้างต้นผลประโยชน์เป็นที่มุ่งหวังทุกความต้องการในอนาคตได้ overcomplicating สิ่งสำหรับยุคปัจจุบัน ไม่สอดคล้องกับ YAGNI เป็นเรื่องยากเล็กน้อยในภายหลังที่จะเขียนการย้ายข้อมูลที่ย้ายจากโมเดลสองตารางของคุณไปเป็นโมเดลโต๊ะเข้าร่วม คุณสามารถทำได้เมื่อความต้องการทางธุรกิจเกิดขึ้น ที่จะทำก่อนที่จะสับสน
  • มันสับสนนักพัฒนาอื่น ๆ ในขณะที่ใช่ฉันจะบอกว่าความคาดหวังของนักพัฒนาเว็บของคุณ (ที่คุณกำลังตรวจสอบการตัดสินใจของที่ปรึกษา) คือการทำความเข้าใจและรับรู้ตารางการเข้าร่วมมันยังซับซ้อนกว่าความจำเป็นและพิจารณาถึงความต้องการทางธุรกิจ มันทำให้เกิดความสับสน

การวิเคราะห์ที่ดี - อย่างไรก็ตามฉันจะไม่บอกว่าฉันมีส่วนร่วมในงานประจำวันของฉันยกเว้นว่าฉันเป็นคนเดียวที่นี่ที่รู้อะไรเกี่ยวกับ db / c # / vb / etc ... ดังนั้นฉันเดาว่าเป็นส่วนหนึ่ง dev เวลาตามค่าเริ่มต้น นี่เป็นโครงการขนาดเล็กพอสมควรดังนั้นที่ปรึกษาจำนวนโต๊ะและร่วมออกจากฉันพูดว่า "wtf" (แต่ขอบคุณชาวบ้านดีฉันตอนนี้ฉันพูดว่า "oic ... ")
จิม

ค่อนข้างเป็นหัวข้อเก่า แต่ยังมีความเกี่ยวข้อง ... การปรับโครงสร้างอาจจะยากมากลองนึกภาพคุณจำเป็นต้องใช้หลายแผนกในอนาคตแทนที่จะเป็นหนึ่ง แต่มี ID แผนกในผู้ใช้เป็น FK คุณน่าจะจบลงด้วยการอ้างอิงซ้ำ (Users.DeptID และ UsersDepartmentsTable) หรือขยะที่สมบูรณ์เช่นรายการที่คั่นด้วยเครื่องหมายจุลภาคใน Users.DeptID หรือ XML ไม่สามารถเพิ่มโซลูชันที่ถูกต้องได้อย่างง่ายดายตามที่ YAGNI หรือ KISS แนะนำ แต่จะถูกขัดขวาง
Erik Hart

0

หากไม่มีโครงสร้างข้อมูลที่ต้องการครบถ้วนฉันไม่สามารถพูดได้ว่ามันแย่มากหรือไม่ แต่อย่างน้อยชิ้นที่แสดงไม่ใช่การออกแบบ "WTF" ดูเหมือนว่าเป็นโครงสร้างข้อมูลแบบปกติที่ 3 (เรามีเหตุผลในทางทฤษฎีเช่นกันที่ 4-rd และ 5-th ด้วย)

การเจรจาบางอย่างอาจมีสถานที่สำหรับ UserDepartmentTable ระหว่างสองโรงเรียนของคีย์ "ธรรมชาติ" และ "ประดิษฐ์" ในส่วนที่แสดง ไม่มีอะไรมากไปกว่าที่ฉันเห็น

การนอร์มัลไลซ์เป็นกฎของนักพัฒนา / นักออกแบบ DB ที่ดีด้วยเหตุผลหลายประการ, * de * การนอร์มัลไลซ์จะถูกนำมาใช้เป็นบางครั้งในช่วงกลางของการพัฒนาเพื่อความรวดเร็ว

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