ฉันควรกำหนดความสัมพันธ์ระหว่างตารางในฐานข้อมูลหรือเพียงแค่ในรหัส?


60

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

ในฐานข้อมูล:

  • แก้ไขข้อมูลจากการออกแบบ ป้องกันข้อผิดพลาดของแอปพลิเคชันซึ่งอาจทำให้ข้อมูลไม่ถูกต้อง

  • ลดเครือข่ายไปกลับแอปพลิเคชันเมื่อทำการแทรก / อัปเดตข้อมูลเนื่องจากแอปพลิเคชันต้องทำแบบสอบถามเพิ่มเติมเพื่อตรวจสอบความถูกต้องของข้อมูล

ในรหัสที่มา:

  • ยืดหยุ่นมากขึ้น

  • ดีกว่าเมื่อขยายไปยังหลายฐานข้อมูลเนื่องจากบางครั้งความสัมพันธ์สามารถข้ามฐานข้อมูลได้

  • ควบคุมความสมบูรณ์ของข้อมูลได้มากขึ้น ฐานข้อมูลไม่จำเป็นต้องตรวจสอบทุกครั้งที่แอปพลิเคชันแก้ไขข้อมูล (ความซับซ้อนสามารถเป็น O (n) หรือ O (n log n) (?)) แต่จะมอบให้กับแอปพลิเคชันแทน และฉันคิดว่าการจัดการความสมบูรณ์ของข้อมูลในแอปพลิเคชันจะทำให้เกิดข้อความแสดงข้อผิดพลาดมากกว่าการใช้ฐานข้อมูล เช่น: เมื่อคุณสร้างเซิร์ฟเวอร์ API หากคุณกำหนดความสัมพันธ์ในฐานข้อมูลและมีบางอย่างผิดปกติ (เช่นไม่มีเอนทิตีที่อ้างอิง) คุณจะได้รับ SQL Exception พร้อมข้อความ วิธีที่ง่ายคือการคืน 500 ให้กับลูกค้าว่ามีข้อผิดพลาด "เซิร์ฟเวอร์ภายใน" และลูกค้าจะไม่ทราบว่าเกิดอะไรขึ้น หรือเซิร์ฟเวอร์สามารถแยกวิเคราะห์ข้อความเพื่อหาว่ามีอะไรผิดปกติซึ่งเป็นวิธีที่น่าเกลียดและผิดพลาดในความคิดของฉัน หากคุณปล่อยให้แอปพลิเคชันจัดการกับสิ่งนี้

มีอะไรอีกไหม?

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

แก้ไข: ขอบคุณทุกคน คำตอบที่ฉันได้รับทั้งหมดชี้ให้เห็นว่าข้อ จำกัด / ความสัมพันธ์ควรกำหนดไว้ในฐานข้อมูล :) ฉันมีอีกหนึ่งคำถามที่มันค่อนข้างออกจากขอบเขตของคำถามนี้ผมเพิ่งโพสต์มันเป็นคำถามเฉพาะกิจการ: จับข้อผิดพลาดฐานข้อมูลสำหรับเซิร์ฟเวอร์ API กรุณาออกความคิดเห็นบางส่วน


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

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

10
บางสิ่งที่ควรค่าแก่การกล่าวถึง ... เมื่อคุณแนะนำปัญหาด้านความสมบูรณ์ให้กับฐานข้อมูลของคุณมันเป็นเครือญาติในการเปิดกล่องแพนดอร่า มันเป็นฝันร้ายที่จะรื้อฟื้นความสมบูรณ์ให้กับฐานข้อมูลที่ผิดปกติ การควบคุมอย่างแน่นหนาในฐานข้อมูลของคุณอาจเป็นเรื่องยุ่งยาก แต่มันจะช่วยให้คุณเจ็บปวดได้มากในระยะยาว
DanK

3
ในซอร์สโค้ด: ในที่สุดคุณก็สามารถเขียนฐานข้อมูลส่วนใหญ่ได้
Blrfl

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

คำตอบ:


70

TL; DR: ข้อ จำกัด ด้านความสัมพันธ์ควรอยู่ในฐานข้อมูล


ใบสมัครของคุณไม่ใหญ่พอ

คุณถูกต้องแน่นอนว่าการบังคับใช้ความสัมพันธ์ข้ามฐานข้อมูลอาจต้องการการบังคับใช้ในแอปพลิเคชัน

ฉันจะชี้ให้เห็นว่าคุณควรตรวจสอบเอกสารของซอฟต์แวร์ฐานข้อมูลที่คุณใช้ก่อนและตรวจสอบข้อเสนอผลิตภัณฑ์ที่มีอยู่ ตัวอย่างเช่นมีข้อเสนอการจัดกลุ่มที่ด้านบนของ Postgres และ MySQL

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

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

ใบสมัครของคุณไม่ถูกต้องเพียงพอ

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

และอันไหนที่คุณเปลี่ยนบ่อยที่สุด?

ฉันเดิมพันบนฐานข้อมูลถูกต้อง, เวลาใดก็ได้

นักพัฒนาของคุณไม่ได้คิดมากพอ

ลดเครือข่ายไปกลับแอปพลิเคชันเมื่อแทรก / อัปเดตข้อมูลเนื่องจากแอปพลิเคชันต้องทำการสืบค้นเพิ่มเติมเพื่อตรวจสอบความถูกต้องของข้อมูล

ธงแดง ! 1

หากคุณกำลังคิด:

  • ตรวจสอบว่ามีการบันทึกอยู่หรือไม่
  • ถ้าไม่ใส่บันทึก

จากนั้นคุณล้มเหลวปัญหาการเกิดพร้อมกันขั้นพื้นฐานที่สุด: กระบวนการ / เธรดอื่นอาจเพิ่มเร็กคอร์ดขณะที่คุณดำเนินการ

หากคุณกำลังคิด:

  • ตรวจสอบว่ามีการบันทึกอยู่หรือไม่
  • ถ้าไม่ใส่บันทึก
  • ตรวจสอบว่าบันทึกถูกแทรกเป็นข้อมูลซ้ำหรือไม่

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

การรักษาข้อ จำกัด ในหลาย ๆ เซสชันนั้นเป็นปัญหาที่ยากมากโปรดดีใจที่มันได้รับการแก้ไขในฐานข้อมูลของคุณ

1 เว้นแต่ฐานข้อมูลของคุณจะใช้คุณสมบัติ Serializable อย่างถูกต้อง แต่น้อยคนนักที่จะทำ


ล่าสุด:

และฉันคิดว่าการจัดการความสมบูรณ์ของข้อมูลในแอปพลิเคชันจะทำให้เกิดข้อผิดพลาด verbose มากกว่าการใช้ฐานข้อมูล เช่น: เมื่อคุณสร้างเซิร์ฟเวอร์ API หากคุณกำหนดความสัมพันธ์ในฐานข้อมูลและมีบางอย่างผิดปกติ (เช่นไม่มีการอ้างอิงเอนทิตี) คุณจะได้รับ SQL Exception พร้อมข้อความ

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

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

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

... ที่ผูกติดอยู่กับจุดความถูกต้องด้านบน ทุกครั้งที่คุณเห็น "500: Internal Server Error" เนื่องจากข้อ จำกัด ของฐานข้อมูลเริ่มทำงานและไม่ได้รับการจัดการหมายความว่าฐานข้อมูลช่วยคุณเนื่องจากคุณลืมจัดการในรหัส


3
ฮ่าฮ่าคุณเขียนสิ่งนี้ในขณะที่ฉันกำลังเขียนความคิดเห็นของฉันเน้นย้ำถึงจุดที่เราทั้งคู่กำลังทำอยู่ ฉันเห็นด้วยอย่างยิ่ง: คุณไม่สามารถทำแม้แต่ความสมบูรณ์หรือข้อ จำกัด ในรหัสที่ไม่ใช่ DB ได้ การทำธุรกรรมไม่สามารถเห็นผลลัพธ์ของผู้อื่นได้จนกว่าพวกเขาจะทำ คุณอาจได้รับภาพลวงตาของความซื่อสัตย์ แต่มันขึ้นอยู่กับเวลาหรือปัญหาการปรับขนาดได้อย่างรุนแรงเนื่องจากการล็อค เฉพาะฐานข้อมูลเท่านั้นที่สามารถทำได้อย่างถูกต้อง
LoztInSpace

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

1
@ Kat11: จริง และการอธิบายตนเองยังมีข้อได้เปรียบที่เครื่องมือสามารถเข้าใจข้อมูลและดำเนินการกับมันได้อย่างง่ายดายซึ่งบางครั้งก็มีประโยชน์
Matthieu M.

1
ข้อโต้แย้งของคุณเกี่ยวกับ MVCC นั้นไม่ถูกต้องในฐานข้อมูลที่ใช้การแยกแบบ SERIALIZABLE ได้อย่างถูกต้อง (PostgreSQL รุ่นที่ทันสมัยทำเช่น - แม้ว่า RDBMS หลัก ๆ จำนวนมากจะไม่ทำก็ตาม) ในฐานข้อมูลดังกล่าวแม้แต่วิธีแรกวิธีการก็จะทำงานได้อย่างถูกต้อง - หากเขียนข้อขัดแย้งพวกเขาจะถูกย้อนกลับเป็นความล้มเหลวในการทำให้เป็นอนุกรม
James_pic

1
ในฐานข้อมูลที่ปรับใช้อย่างถูกต้องถ้าคุณทำธุรกรรมที่ได้ทำสำเร็จไปแล้วมีการสั่งซื้อบางอย่าง (ซึ่งอาจไม่เหมือนกับการสั่งซื้อนาฬิกาแขวน) เช่นถ้าคุณใช้งานทั้งหมดในลำดับ (โดยไม่มีการทำงานพร้อมกัน) ตามลำดับผลลัพธ์ทั้งหมดจะเหมือนกันทุกประการ เป็นการยากที่จะทำให้ถูกต้องและสเปค SQL นั้นคลุมเครือพอที่คุณสามารถโน้มน้าวใจตัวเองได้ว่ามันโอเคที่จะอนุญาตให้เขียนเบ้ระดับ SERIALIZABLE ดังนั้นผู้ค้า DB หลายคนปฏิบัติต่อ SERIALIZABLE เหมือนกับ SNAPSHOT ISOLATION (ฉันมองคุณ Oracle)
James_pic

119

ฐานข้อมูลไม่จำเป็นต้องตรวจสอบความถูกต้องของข้อมูลทุกครั้งที่แอปพลิเคชันแก้ไขข้อมูล

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


5
@ dan1111 ฉันไม่เข้าใจความคิดเห็นของคุณ ... คุณกำลังพูดว่า: ข้อ จำกัด ง่าย ๆ ถูกบังคับใช้โดยฐานข้อมูลดังนั้นพวกเขาจึงไม่เป็นปัญหาสำหรับรหัสแอปพลิเคชันข้อ จำกัด ที่ซับซ้อนกว่านั้นยากที่จะนำไปใช้ หรือคุณกำลังบอกว่าการใช้ข้อ จำกัด ที่ซับซ้อนโดยใช้ทริกเกอร์ฐานข้อมูล (และกลไกที่คล้ายกัน) นั้นซับซ้อนเกินไปและดีกว่าที่จะนำไปใช้ในโค้ดแอปพลิเคชัน
Bakuriu

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

17
Anecdotally ตามความเห็นของ @ LoztInSpace ฉันเคยทำงานให้กับ บริษัท (แย่มาก) ที่หนึ่งในตารางนั้นถูกตั้งค่าในลักษณะที่แทนที่จะปล่อยให้ DB อัตโนมัติเพิ่ม ID ID แอปพลิเคชันใช้ ID แถวสุดท้าย เพิ่มหนึ่งมันและใช้เป็น ID ใหม่ น่าเสียดายที่มีการแทรกรหัสประจำตัวที่ซ้ำกันประมาณสัปดาห์ละครั้งซึ่งจะทำให้แอปพลิเคชันหยุดทำงาน ..
Trotski94

9
@ dan1111 คุณไม่เคยเขียนบั๊กในแอปพลิเคชันใช่มั้ย
user253751

4
@DavidPacker ผมอาจจะเห็นด้วย แต่เมื่อคุณมีลูกค้าหลายเข้าถึงฐานข้อมูลที่คุณสามารถเพียงการบังคับใช้ข้อ จำกัด ในฐานข้อมูล นอกจากนั้นคือคุณเริ่มล็อคตารางขายส่งแทนที่จะเป็นแถวด้วยการเข้าชมที่มีประสิทธิภาพ
Iker

51

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

ในบางจุดอาจต้องมีการแก้ไขสคริปต์ภายในฐานข้อมูลหรือคุณอาจต้องย้ายข้อมูลจากตารางหนึ่งไปยังอีกตารางหนึ่งในการปรับใช้

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

นี่คือที่ความสมบูรณ์ของระดับฐานข้อมูลจะบันทึกเบคอนของคุณ


นอกจากนี้รูปภาพนักพัฒนาซอฟต์แวร์ที่มีบทบาทของคุณที่ บริษัท นี้หลังจากที่คุณจากไปและมอบหมายให้ทำการเปลี่ยนแปลงฐานข้อมูล

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


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

9
@nikonyrh ฉันจะไม่ทำอย่างนั้น มีข้อ จำกัด เพื่อให้แอปพลิเคชันสามารถใช้ข้อมูลที่สอดคล้องกัน การปิดการใช้งาน FK เพียงเพื่อให้ได้มาเป็นความบ้าคลั่ง
Paddy

5
ตกลง นอกจากนี้แม้ว่าแอปพลิเคชันของคุณเป็นไคลเอนต์เดียวคุณอาจมีแอปพลิเคชันรุ่นต่าง ๆ ที่พยายามบังคับใช้ข้อ จำกัด ที่แตกต่างกันเล็กน้อย โดยปกติแล้วความฮือฮาจะตามมา (ก็ไม่จริงมันเป็น 'ความโกลาหลและความยุ่งยาก' มากกว่า 'ความฮือฮา')
Iker

5
ฉันสามารถยืนยันได้อย่างนี้ ในกรณีของฉันฉันติดอยู่กับ MyISAM ซึ่งไม่รองรับคีย์ต่างประเทศจริง ๆ ดังนั้นฉันจึงลงเอยด้วยข้อมูล 250GB พร้อมด้วยความสมบูรณ์ของแอปพลิเคชัน เมื่อมันเริ่มทำการตัดแต่งข้อมูลเพื่อให้ Backlog มีขนาดที่จัดการได้มากขึ้นและเมื่อเห็นได้ชัดว่าแอปพลิเคชันนั้นไม่สามารถจัดการกับสิ่งนี้ได้ทั้งหมดความสับสนวุ่นวายเกิดขึ้น ฉันไม่รู้ว่าทำไมฉันถึงใช้อดีตกาล สิ่งนี้ยังคงเกิดขึ้นในขณะนี้และปัญหา (สองปี) ยังไม่ได้รับการแก้ไข * sniff *
Lightness Races กับโมนิก้า

1
ฉันจะยืนยันว่าฐานรหัสที่ดีควรทำให้ง่ายต่อการเขียนสคริปต์แบบใช้ครั้งเดียวโดยใช้เลเยอร์การคงอยู่จากแอปพลิเคชันของคุณอย่างน้อยก็อย่างรวดเร็วเหมือนกับการเขียน SQL ดิบ 'การแก้ไขโค้ดแอปพลิเคชันของคุณ' ไม่ควรจำเป็นสำหรับสคริปต์แบบใช้ครั้งเดียว
Jonathan Cast

17

คุณควรมีความสัมพันธ์ในฐานข้อมูล

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

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


1
จริง ฉันควรจะบอกว่าประสิทธิภาพของการตรวจสอบข้อ จำกัด จะได้รับการจัดการในฐานข้อมูลได้ดีกว่าในแอปพลิเคชัน
Kirk Broadhurst

13
  • เราไม่ได้อยู่ใน back-end เดียวอีกต่อไป <-> โลกหน้าเดียว
  • โซลูชันส่วนใหญ่เกี่ยวข้องกับส่วนหน้าของเว็บส่วนหน้าของอุปกรณ์เคลื่อนที่แบตช์ฟรอนต์เอนด์และส่วนหน้าของ iPad เป็นต้น
  • เอ็นจิ้นฐานข้อมูลมีโค้ดที่ผ่านการทดสอบหลายพันเส้นแล้วซึ่งได้รับการปรับให้เหมาะสมเพื่อบังคับใช้การอ้างอิงแบบสมบูรณ์

คุณสามารถที่จะเขียนและทดสอบ Referential integrity บังคับใช้รหัสเมื่อคุณมีปัญหาในการแก้ปัญหาโดเมนเพื่อเขียนรหัสหรือไม่


2
"เราไม่ได้อยู่ใน back-end เดียวอีกต่อไป <-> โลกหน้าเดียว" พวกเราไม่เคย? ไม่กี่ปีที่ผ่านมาฉันทำงานกับระบบฐานข้อมูลที่มีโปรแกรมที่เขียนด้วยภาษาต่าง ๆ อย่างน้อยสองโหลที่เข้าถึงได้ บางรายการมีการเปิดตัวครั้งแรกในปี 1970
Mike Sherrill 'Cat Recall'

2

หากคุณไม่ตรวจสอบความถูกต้องของข้อมูลข้อ จำกัด ความสัมพันธ์ ฯลฯ ในระดับฐานข้อมูลนั่นหมายความว่าทุกคนที่เข้าถึงฐานข้อมูลการผลิตได้ง่ายกว่ามาก (ผ่านไคลเอนต์อื่นรวมถึงเครื่องมือการเข้าถึงฐานข้อมูล) เพื่อทำให้ข้อมูลของคุณยุ่งเหยิง

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

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


1

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

รหัสซ้ำ

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

ความพยายาม

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

อย่างมีประสิทธิภาพ

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

ควบคุม

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

คะแนนปิด

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

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


1
หากผู้คนยอมรับคำตอบที่ดีเพราะไม่เห็นด้วยกับความเชื่อของพวกเขา SE StackExchange ก็จะกลายเป็นสถานที่ที่เลวร้ายกว่า
Carl Leth

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

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

0

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

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

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

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

หมายความว่าถ้าฉันรู้แล้วว่ามีชิ้นส่วนที่จำเป็นต้องเก็บไว้ในฐานข้อมูลที่แตกต่างกันจากนั้นฉันสามารถวางไว้ที่นั่นแล้วกำหนดเป็นแบบแยกส่วนได้ ขวา?

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

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

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


0

คุณมีคำตอบที่ดีมาก แต่มีบางประเด็นเพิ่มเติม

ความถูกต้องของข้อมูลเป็นสิ่งที่ฐานข้อมูลถูกออกแบบมาให้ทำ

การทำงานพร้อมกันอย่างเหมาะสมเช่นการลบ FK ที่ระดับแอปพลิเคชันน่ากลัว

ความเชี่ยวชาญด้านความสมบูรณ์ของข้อมูลอยู่กับ DBA

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

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

คุณอาจต้องจัดการข้อมูลโดยตรงผ่าน SQL หรือ TSQL
ไม่มีใครจำกฎข้อมูลทั้งหมดได้


0

คำถามของคุณไม่สมเหตุสมผล: หากคุณสามารถเปลี่ยนฐานข้อมูลได้ก็คือรหัสหากคุณไม่สามารถเปลี่ยนฐานข้อมูลได้คุณจะต้องสร้างข้อ จำกัด ที่อื่น

ฐานข้อมูลที่คุณสามารถเปลี่ยนได้คือรหัสเท่า ๆ กับ ruby, javascript, c # หรือ ada

คำถามเกี่ยวกับตำแหน่งที่จะวางข้อ จำกัด ในระบบของคุณควรทำให้ความน่าเชื่อถือราคาและความสะดวกในการพัฒนาลดลง


0

มีคำตอบที่ดีมากมายที่นี่ ฉันจะเพิ่มว่าหากคุณมีแอปที่เขียนด้วยภาษา Y คุณสามารถสร้างรหัสที่เหมือนข้อ จำกัด ของฐานข้อมูลใน Y จากนั้นมีคนต้องการเข้าถึงฐานข้อมูลของคุณโดยใช้ภาษา Z คุณจะต้องเขียนรหัสเดียวกันอีกครั้ง พระเจ้าช่วยคุณถ้าการนำไปปฏิบัตินั้นไม่เหมือนกันทั้งหมด หรือเมื่อผู้ใช้ทางธุรกิจที่มีความรู้เชื่อมต่อกับฐานข้อมูลของคุณโดยใช้ Microsoft Access

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

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

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