ออกแบบฐานข้อมูล - เก็บสถานะหรือคำนวณสถานะทุกครั้งหรือไม่


17

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

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

ฉันคิดว่าวิธีแรกนั้นซับซ้อนและมีข้อผิดพลาดมากกว่า แต่จะทำงานได้ดีกว่าวิธีที่สอง

ปกติแล้ววิธีนี้ทำได้อย่างไรหรืออะไรคือวิธีการที่ดีกว่า


1
ขึ้นอยู่กับปัจจัยหลายประการ: DB พาร์ติชั่นของคุณหรือไม่? คุณคาดหวังจำนวนแถว / ผู้ใช้กี่คน? คุณคาดหวังฐานข้อมูลขนาดเท่าใด (หรือผู้ใช้ทั้งหมดกี่คน) คุณคาดหวังต่อคำขอกี่วินาที? ทั้งหมดนี้ไม่จำเป็นต้องมีความถูกต้อง แต่บางความคิดที่หยาบ ...
โอเมอร์อิคบาล

10
+1 นี่คือคำถามฐานข้อมูลเชิงสัมพันธ์คลาสสิก จะทำให้ปกติหรือไม่ที่จะทำให้ปกติ? นั่นคือคำถาม. ไม่ว่าจะเป็นขุนนางในสคีที่จะได้รับสลิงและลูกศรของการทำซ้ำที่ชั่วร้ายหรือใช้ทริกเกอร์และโดยการจ้างให้จบพวกเขา?
Ross Patterson

ฉันยืนยันว่านี่เป็น Rel คลาสสิก ฐานข้อมูล คำถามควรมีคำตอบในเว็บไซต์แล้วควรปิดเป็น DUP หรือเราไม่มีคำตอบและควรเปิดทิ้งไว้
mattnz

คำตอบ:


14

วิธีนี้เป็นวิธีปกติหรือวิธีที่ดีกว่าคืออะไร?

วิธีที่ดีที่สุดคือลองครั้งแรกโดยไม่มีฟิลด์พิเศษวัดประสิทธิภาพและถ้าหากมันช้าเกินไปจริง ๆ คุณลองปรับให้เหมาะสม นี่อาจหมายถึงการเปลี่ยนไปใช้วิธีแรกของคุณโดยใช้ฟิลด์พิเศษ แต่คุณควรลองทดสอบตัวเลือกอื่นเช่นกันวางดัชนีพิเศษลงในฟิลด์ที่รวมกัน ("ยังไม่ได้อ่าน", "userID") ในข้อความของคุณ


2
วิธีที่ดีที่สุดคือ (ไปกับวิธีที่ง่ายกว่าก่อน) กฎทั่วไปดีกว่าเฉพาะ fwiw (+1 สำหรับ "ทดสอบ!")
DougM

9

วิธีการแก้ปัญหาตำรา acccording เพื่อทฤษฎีฐานข้อมูลจะมีค่าไม่มีในฐานข้อมูลของคุณซึ่งขึ้นอยู่กับค่าของข้อมูลอื่น ๆ เพราะเหล่านี้มีการอ้างอิงสกรรมกริยา การมีเขตข้อมูลที่คำนวณค่าตามเขตข้อมูลอื่นเป็นการละเมิดการทำให้เป็นมาตรฐานเนื่องจากจะนำไปสู่ข้อมูลซ้ำซ้อน

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


4
ปัญหาความมั่นคงเป็นเรื่องง่ายที่จะเลียกับทริกเกอร์ที่ปรับเปลี่ยนเคาน์เตอร์บนหรือINSERT DELETE(หรือUPDATEเพื่อพิจารณาการเปลี่ยนแปลงของเจ้าของข้อความ) DBMS ที่ดีจะทำการดำเนินการและเรียกใช้ทริกเกอร์ในการทำธุรกรรมเดียวกันดังนั้นจะเกิดขึ้นทั้งหมดหรือไม่มีเลย
Blrfl

4

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

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

เดินทางไปที่ db ทุกครั้งที่มีการอ่านข้อความเพื่อตั้งค่าสถานะ IsRead? เขตข้อมูลก็เพียงพอโดยไม่มีการคำนวณใหม่ของเขตข้อมูลอื่น

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


+1 สำหรับการกล่าวถึงปัญหาด้านประสิทธิภาพด้วยการทำให้เขตข้อมูลนับเป็นปัจจุบัน
winkbrace

0

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

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

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