คีย์หลักแบบคอมโพสิตคือการปฏิบัติที่ไม่ดี? [ปิด]


14

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

คำถามของฉันอ้างอิงจากบทความนี้

ข้อผิดพลาดในการออกแบบฐานข้อมูล

ส่วนเกี่ยวกับคีย์หลักผสม:

การปฏิบัติที่ไม่ถูกต้องหมายเลข 6: คีย์หลักแบบรวม

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

ภาพของคีย์หลักรวม

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

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


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

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

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

1
GUID ดีกว่า INTEGER อย่างไร [Serial | Auto_Increment | ตัวตน | <whething_integer_you_like>]?
Vérace

4
ฉันจะไม่จ้างผู้เขียนคนนั้น
paparazzo

คำตอบ:


31

จะบอกว่าการใช้งาน"Composite keys as PRIMARY KEY is bad practice"เป็นเรื่องไร้สาระที่สุด!

Composite PRIMARY KEYs มักจะเป็น "สิ่งที่ดี" และเป็นวิธีเดียวที่จะจำลองสถานการณ์ทางธรรมชาติที่เกิดขึ้นในชีวิตประจำวัน!

นึกถึงตัวอย่างการสอนฐานข้อมูลคลาสสิก 101 ของนักเรียนและหลักสูตรและหลายหลักสูตรที่นักเรียนหลายคนใช้!

สร้างหลักสูตรตารางและนักเรียน:

CREATE TABLE course
(
  course_id SERIAL,
  course_year SMALLINT NOT NULL,
  course_name VARCHAR (100) NOT NULL,
  CONSTRAINT course_pk PRIMARY KEY (course_id)
);


CREATE TABLE student
(
  student_id SERIAL,
  student_name VARCHAR (50),
  CONSTRAINT student_pk PRIMARY KEY (student_id)
);

ฉันจะให้คุณตัวอย่างในภาษา PostgreSQL (และMySQL ) - ควรทำงานกับเซิร์ฟเวอร์ใด ๆ ที่มีการปรับแต่งเล็กน้อย

ตอนนี้คุณเห็นได้ชัดว่าต้องการที่จะติดตามการที่นักศึกษามีการศึกษาซึ่งหลักสูตร - เพื่อให้คุณมีสิ่งที่เรียกว่าjoining table(ที่เรียกว่าlinking, many-to-manyหรือm-to-nตาราง) พวกเขาเป็นที่รู้จักassociative entitiesในศัพท์แสงทางเทคนิคมากขึ้น!

1คอร์สสามารถมีนักเรียนได้จำนวนมาก นักเรียน
1คนสามารถเรียนได้หลายหลักสูตร

ดังนั้นคุณสร้างตารางการเข้าร่วม

CREATE TABLE course_student
(
  cs_course_id INTEGER NOT NULL,
  cs_student_id INTEGER NOT NULL,

  -- now for FK constraints - have to ensure that the student
  -- actually exists, ditto for the course.

  CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
  CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);

ตอนนี้วิธีเดียวที่จะทำให้ตารางนี้อย่างสมเหตุสมผลPRIMARY KEYคือKEYการรวมหลักสูตรและนักเรียนเข้าด้วยกัน ด้วยวิธีนี้คุณจะไม่ได้รับ:

  • สำเนาของนักเรียนและการรวมกันของหลักสูตร

    • หลักสูตรสามารถมีนักเรียนคนเดียวกันลงทะเบียนเพียงครั้งเดียวและ

    • นักเรียนสามารถลงทะเบียนเรียนในหลักสูตรเดียวกันเพียงครั้งเดียวเท่านั้น

  • คุณยังมีการค้นหาทำพร้อมKEYในหลักสูตรต่อนักเรียน - AKA ดัชนีครอบคลุม ,

  • มันเป็นเรื่องเล็กน้อยที่จะหาหลักสูตรที่ไม่มีนักเรียนและนักเรียนที่กำลังเรียนอยู่!

    - The DB-ซอตัวอย่างเช่นมีข้อ จำกัด PK พับลงในตาราง CREATE - ก็สามารถทำได้ด้วยวิธีใด ฉันชอบที่จะมีทุกอย่างในคำสั่ง CREATE TABLE


ALTER TABLE course_student 
ADD CONSTRAINT course_student_pk 
PRIMARY KEY (cs_course_id, cs_student_id);

ทีนี้คุณก็สามารถทำได้ถ้าคุณค้นพบว่าการค้นหานักเรียนโดยเรียนช้าใช้ a UNIQUE INDEX(sc_student_id, sc_course_id)

ALTER TABLE course_student 
ADD CONSTRAINT course_student_sc_uq  
UNIQUE (cs_student_id, cs_course_id);

นอกจากนี้ไม่มี bullet เงินสำหรับการเพิ่มดัชนี - พวกเขาจะทำINSERTและUPDATEs ช้าลง แต่ในประโยชน์ที่ดีของอย่างมหาศาลลดลงSELECTครั้ง! ขึ้นอยู่กับผู้พัฒนาที่จะตัดสินใจจัดทำดัชนีโดยให้ความรู้และประสบการณ์ แต่ถ้าจะพูดว่าคอมโพสิตPRIMARY KEYนั้นแย่เสมอก็ผิด

ในกรณีของการเข้าร่วมตารางพวกเขามักจะเหมาะสมเท่านั้น PRIMARY KEY ! การเข้าร่วมตารางยังเป็นวิธีเดียวในการสร้างแบบจำลองสิ่งที่เกิดขึ้นในธุรกิจหรือธรรมชาติหรือในทุก ๆ ทรงกลมที่ฉันนึกได้!

PK นี้ยังมีการใช้งานcovering indexซึ่งสามารถช่วยเพิ่มความเร็วในการค้นหา ในกรณีนี้มันจะมีประโยชน์อย่างยิ่งถ้ามีใครค้นหาเป็นประจำ (course_id, student_id) ซึ่งใคร ๆ ก็นึกออกมักจะเป็นกรณี!

นี่เป็นเพียงตัวอย่างเล็ก ๆ น้อย ๆ ที่คอมโพสิตPRIMARY KEYสามารถเป็นความคิดที่ดีมากและเป็นวิธีเดียวที่มีเหตุผลในการสร้างแบบจำลองความเป็นจริง! จากด้านบนของหัวของฉันฉันสามารถคิดอื่น ๆอีกมากมาย

ตัวอย่างจากงานของฉันเอง!

พิจารณาตารางเที่ยวบินที่มี flight_id รายชื่อสนามบินต้นทางและปลายทางที่มาถึงและเวลาที่เกี่ยวข้องแล้วยังมีตาราง cabin_crew กับสมาชิกลูกเรือ!

วิธีเดียวที่มีสตินี้สามารถจำลองได้คือให้มีตาราง flight_crew พร้อม flight_id และ crew_id เป็นสิ่งที่แนบมาและมีสติเพียงอย่างเดียวPRIMARY KEYคือใช้คีย์ผสมของสองฟิลด์!


2
ในตัวอย่างของหลักสูตรและนักเรียนอาจเป็นไปได้สำหรับ course_student ที่มีidคีย์หลักและดัชนีที่ไม่ซ้ำกันcs_student_id cs_course_idและมีผลลัพธ์เหมือนกันหรือไม่
hackvan

2
ทำไมทรัพยากรสิ้นเปลืองทำเช่นนั้น? ด้วย PK (course_id, student_id) ตามคำนิยามคุณมีดัชนีที่ไม่ซ้ำในฟิลด์เหล่านั้นแล้ว! ดัชนีเฉพาะบน (student_id, course_id) อาจใช้ในการเร่งการค้นหา - พูดว่าหากคุณกำลังมองหานักเรียนที่ไม่ได้เรียนหลักสูตรใด ๆ แต่การตัดสินใจนั้นอาจเป็นวิธีปฏิบัติ แต่ในวันนี้มีพื้นที่จัดเก็บค่อนข้างน้อย ฉันจะแนะนำอีกครั้งโดยเฉพาะอย่างยิ่งเนื่องจากมีใครคิดว่าตารางจะไม่ได้รับการปรับปรุงบ่อยมาก
Vérace

1
ยอมรับอย่างสมบูรณ์สำหรับตารางลิงก์ - ฉันกำลังทำงานกับหลาย ๆ คนในตอนนี้ อย่างไรก็ตามเมื่อฉันใส่หมวก C # ของฉันฉันกำลังทำงานกับเครื่องกำเนิดไฟฟ้าย้อนกลับและสร้างชั้นเรียนที่มีประโยชน์ (ค้นหาบันทึก ฯลฯ ) สำหรับชั้นถัดไปขึ้น ฉันพบปัญหาใหญ่ - แป้นคอมโพสิตกลายเป็น PITA สำหรับการมีรหัสบันทึก / ค้นหาทั่วไป ใช่ฉันอาจกลับไปที่ไฟล์ EDMX แต่ฉันยังต้องแก้ไขรหัสกรณีพิเศษ (นับคอลัมน์ Pkey หรือไม่) หรือเพิ่มคีย์ตัวแทนเสมือน (ไม่ชอบและต้องการข้อ จำกัด เพิ่มเติมที่เป็นเอกลักษณ์ :() ดังนั้นฉันเดา คนที่ไม่ชอบคอมโพสิตพูดจากรหัสเลเยอร์ของแอป
Richard Griffiths

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

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

3

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

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

Microsoft SQL Server มีคุณสมบัติที่แตกต่างกัน แต่มีความเกี่ยวข้องของ "ดัชนีคลัสเตอร์" ที่ควบคุมการจัดเก็บทางกายภาพของข้อมูลตามลำดับดัชนีและยังใช้ในดัชนีอื่น ๆ โดยค่าเริ่มต้นคีย์หลักจะถูกสร้างขึ้นเป็นดัชนีคลัสเตอร์ แต่คุณสามารถเลือกที่ไม่ใช่คลัสเตอร์แทนโดยเฉพาะอย่างยิ่งหลังจากสร้างดัชนีคลัสเตอร์ ดังนั้นคุณสามารถมีคอลัมน์จำนวนเต็มที่สร้างเป็นดัชนีคลัสเตอร์และพูดชื่อไฟล์ nvarchar (128 ตัวอักษร) เป็นคีย์หลัก สิ่งนี้อาจดีกว่าเนื่องจากคีย์ดัชนีคลัสเตอร์นั้นแคบแม้ว่าคุณจะจัดเก็บชื่อไฟล์เป็นคำต่างประเทศในตารางอื่น - แม้ว่าตัวอย่างนี้เป็นกรณีที่ดีสำหรับการไม่ทำเช่นนั้น

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

https://www.techopedia.com/definition/5547/primary-keyอธิบายตัวอย่างของการเลือกว่าจะเก็บข้อมูลด้วยหมายเลขประกันสังคมของลูกค้าเป็นรหัสลูกค้าในตารางข้อมูลทั้งหมดหรือสร้าง customer_id แบบสุ่มเมื่อคุณ ลงทะเบียนพวกเขา จริงๆแล้วนี่เป็นการละเมิด SSN ที่ร้ายแรงนอกจากจะใช้งานได้หรือไม่ มันเป็นค่าข้อมูลส่วนบุคคลและเป็นความลับ

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

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


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