การทำให้เป็นมาตรฐาน: ถือว่าเป็นไปตามการแยกค่าคงที่และตัวเลขเช่นปีลงในตารางของตัวเองหรือไม่?


16

ฉันกำลังสนทนากับผู้ออกแบบฐานข้อมูลคนอื่นเกี่ยวกับการทำให้เป็นมาตรฐาน ในตัวอย่างนี้เรามีตาราง GameTitles และแต่ละระเบียนต้องมีปีที่เกมวางจำหน่าย เขาบอกว่า 2NF มอบอำนาจให้ทุกอย่างต้องเป็นมาตรฐานดังนั้นเพื่อให้เป็นไปตามข้อกำหนดฟิลด์ปีควรแยกออกเป็นตาราง ReleaseYears ด้วยคีย์หลักของตัวเองที่อ้างอิงโดยตาราง GameTitles ฉันบอกว่ามันควรจะยังคงเป็นเขตข้อมูลในตาราง GameTitles เอง

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

คิดเกี่ยวกับเรื่องนี้?

แก้ไข:หมายถึงการโพสต์สิ่งนี้บน StackOverflow ใครสามารถลงคะแนนเพื่อลบหรือตั้งค่าสถานะนี้เพื่อความสนใจได้


6
ทำไมถึงเป็นเช่นนั้น ดูเหมือนว่าเป็นแบบที่ดีที่นี่
Leigh Riffel

คำถามที่ฉันต้องการถามคือคุณกำลังถามเกี่ยวกับการทำให้เป็นมาตรฐานหรือความต้องการการผลิตจริงหรือไม่? สำหรับการผลิตฉันจะถามว่าเป็นสิ่งที่ถูกต้องทำอย่างไร
jcolebrand

คำตอบ:


14

ตัวออกแบบฐานข้อมูลอื่นนั้นผิด แต่เหตุผลของคุณก็ผิดเช่นกัน สมมติว่าคุณเริ่มต้นด้วยตารางนี้ซึ่งมีคีย์ตัวเลือกเดียว "game_title"

Table: game_titles

game_title                      year_first_released
--
The first game                  1998
The second game                 1999
Best game: the third one        2001
The fourth game                 2003
Forty-two, the end of games     2011

คุณประเมินว่ามันอยู่ใน 2NF หรือไม่โดยถามคำถามเหล่านี้กับตัวเอง

ถาม: ก่อนอื่นมันอยู่ใน 1NF หรือไม่?

ตอบ: ใช่มันคือ

ถาม: อะไรคือคุณสมบัติหลัก (คุณลักษณะที่เป็นส่วนหนึ่งของคีย์ตัวเลือก)

ตอบ: "game_title" เป็นคุณลักษณะเฉพาะเท่านั้น

ถาม: อะไรคือคุณสมบัติที่ไม่สำคัญ?

ตอบ: "year_first_released" เป็นเพียงรายการเดียว

ถาม: "year_first_released" ขึ้นอยู่กับฟังก์ชันทั้งหมดของ "game_title" หรือเพียงบางส่วน

ตอบ: คีย์ผู้สมัคร แต่เพียงผู้เดียว "game_title" เป็นคอลัมน์เดียว มันไม่มีแม้กระทั่งชิ้นส่วน ดังนั้น "year_first_released" จึงขึ้นอยู่กับฟังก์ชันทั้งหมดของ "game_title"

voila คุณพบ 2NF แล้ว

คุณสามารถตัดคำศัพท์ที่เป็นทางการออกมาได้โดยถามก่อนว่าเป็น 1NF หรือไม่จากนั้นตอบคำถามนี้

ถาม: มีคีย์ตัวเลือกใด ๆ ที่ประกอบกันอย่างไร

ตอบ: ไม่ใช่

voila คุณพบ 2NF อีกครั้ง

ตามคำนิยามสำหรับตารางที่ละเมิด 2NF จะต้องมีคีย์ตัวเลือกอย่างน้อยหนึ่งตัวที่มีมากกว่าหนึ่งคอลัมน์

นี่คือเหตุผลที่ปฏิเสธความเห็นของเพื่อนของคุณ

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

ไม่มีเหตุผลใดที่เกี่ยวข้องกับว่าตารางอยู่ใน 2NF หรือไม่

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

โอ้และตารางสองคอลัมน์ที่ฉันให้ไว้ข้างต้น - มันอยู่ใน 5NF


2
ทำได้ดีมาก ฉันถูกล่อลวงให้โพสต์คำตอบที่ไม่ได้พูดอะไรนอกจากประโยคแรกของคุณ ... "ผู้ออกแบบฐานข้อมูลอื่นผิดปกติ" คุณได้อธิบายถึงสาเหตุที่ดีมาก
Mark Storey-Smith

5

การสร้างตารางแยกต่างหากสำหรับคุณลักษณะใด ๆ ไม่เกี่ยวข้องกับการทำให้เป็นมาตรฐาน 2NF, 3NF, BCNF, 4NF, 5NF ล้วน แต่เกี่ยวข้องกับการกำจัดการพึ่งพาที่ไม่สำคัญ หากคุณลบแอททริบิวต์เดี่ยวใด ๆ ไปยังตารางใหม่และแทนที่ด้วยแอททริบิวต์คีย์แบบต่างประเทศการอ้างอิงในตารางจะเป็นแบบเดียวกับเมื่อก่อน - ดังนั้นเวอร์ชันที่แก้ไขของตารางจะไม่ถูกทำให้เป็นมาตรฐานมากกว่าหรือน้อยกว่าปกติ เมื่อก่อน


ฉันต้องการเพิ่มบางอย่างลงในสิ่งนี้ แต่ไม่แน่ใจว่าทำอะไร คุณกำลังบอกว่าการย้ายบางสิ่งบางอย่างไปยังตารางที่มีความสัมพันธ์ 1: 1 (ทั้ง 1 คีย์เป็น 1 ค่าตามจริงในกรณีนี้หรือหนึ่งแถวต่อหนึ่งแถว) ไม่ให้ประโยชน์หากการค้นหาไม่จำเป็นใช่ไหม แต่มีประโยชน์การค้นหาที่อาจเกิดขึ้นถ้าคุณไม่ค่อยต้องการปีและคุณเพียงดูที่ช่วง 255 ปีหรือน้อยกว่า คุณอาจจะรอดไปได้ด้วยการบันทึกที่ไม่กี่ไบต์ที่นี่ แต่เนื่องจากโดยปกติแล้วจะถูกจัดสรรที่ 4bytes ต่อไปนี่ไม่ใช่ข้อสันนิษฐานที่สมเหตุสมผล
jcolebrand

1
@ jcolebrand: เห็นด้วยกับสิ่งที่คุณพูด ยังคงเป็นคำตอบสำหรับคำถามที่เหมือนกัน: ไม่ว่าคุณจะทำหรือไม่มีอะไรที่จะทำกับการฟื้นฟูตามปกติ
nvogel

ฉันเห็นด้วย อย่างที่ฉันพูดไปฉันเป็นคนใจแคบ "ฉันรู้สึกเหมือนว่า OP ไม่มีอะไรบางอย่างที่นี่" ... เพราะฉันไม่แน่ใจว่าจะไปกับแนวคิดนี้ได้อย่างไร
jcolebrand

5

จากมุมมองของฉันตารางปีที่แยกต่างหากจะสมเหตุสมผลถ้า "ปีที่วางจำหน่าย" ไม่ใช่ปีปฏิทิน แต่เช่นปีงบประมาณซึ่งอาจครอบคลุมหลายปีปฏิทิน (เช่นไปจากตุลาคมถึงตุลาคม)

ตารางนั้นจะถือคำจำกัดความ (วันที่เริ่มต้นและสิ้นสุดจริง) ของปีบัญชี


1
+1 คุณต้องการเพียงตารางถ้ามันเป็นไปได้ที่มีแอตทริบิวต์ :)
แจ็คดักลาส

2

จากhttp://en.wikipedia.org/wiki/Second_normal_form :

ตาราง 1NF อยู่ใน 2NF ถ้าหากให้คีย์ตัวเลือก K และแอตทริบิวต์ A ใด ๆ ที่ไม่ได้เป็นส่วนประกอบของคีย์ตัวเลือก A ขึ้นอยู่กับผลรวมของ K มากกว่าส่วนหนึ่งของมัน

คุณไม่ได้ระบุว่าปีนี้เป็นส่วนหนึ่งของรหัสผู้สมัครหรือไม่ แต่ฉันไม่แน่ใจว่ามันสำคัญเพราะในกรณีใดกรณี 2NF จะพอใจเท่าปีที่เกี่ยวข้อง

ในระดับปฏิบัติมันเป็นความคิดที่ดีที่จะแยกปีด้วยเหตุผลทั้งหมดที่คุณระบุไว้


2

ฉันไม่ชอบการโต้เถียงกับตารางแยกเนื่องจากขนาดหรือว่ามันจะมีแถวที่ไม่ได้ใช้ แม้ว่าคุณจะใส่ 1,000 ปีในตารางนี้ขนาดจะเล็กน้อย

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

อาร์กิวเมนต์อาจแตกต่างกันสำหรับตารางปฏิทินโดยที่แต่ละแถวแสดงวันและสามารถมีแอตทริบิวต์อื่น ๆ (วันในสัปดาห์ UTC ชดเชยไม่ว่าจะเป็นวันหยุด ฯลฯ )

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

WHERE othertable.year = 2011

แทน

WHERE dt >= 20110101 AND dt < 20120101

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


1

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

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

สำหรับกรณีเฉพาะนี้ฉันพูดอีกครั้งว่าคำตอบของ Catcall นั้นถูกต้อง แต่แค่ต้องการชี้ให้เห็น (ขออภัยยังไม่มีตัวแทนความคิดเห็นเพียงพอ)

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