กดไลค์หรือโหวตโพสต์


10

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

เป็นครั้งแรก

โพสต์:

id   head   message   datepost   likes   dislikes
1     ab    anchdg     DATE      1,2,3   7,55,44,3

ในทางข้างต้นidเป็น postid ในคอลัมน์1,2,3ไลค์คือรหัสของผู้ใช้ที่ชอบหรืออัปเดตโพสต์หรือบล็อก 7,55,44,3คือรหัสของผู้ใช้ที่ไม่ชอบหรือลดระดับโพสต์หรือบล็อก

ที่สอง

โพสต์:

id    head  message   datepost
1     ab    anchdg     DATE

ชอบอะไร:

id    postid    userid
1       1         1
2       2         2

ไม่ชอบ:

id    postid    userid
1       1         7
2       1         55

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

ดังนั้นฉันอยากจะรู้ว่าวิธีไหนดีกว่า & มาตรฐานในการบรรลุภารกิจนี้?


4
ฉันสมมติว่าผู้ใช้ไม่สามารถถูกใจและไม่ชอบโพสต์ได้หรือไม่ ถ้าเป็นเช่นนั้นฉันจะมีหนึ่งตารางสำหรับสิ่งที่ชอบและไม่ชอบโดยมีคอลัมน์ BIT (1 อันสำหรับเช่น, 0 สำหรับคนที่ไม่ชอบ)
dwjv

1
หรือ 1 และ -1 เพื่อให้ได้ผลรวมที่ง่ายขึ้น
jkavalik

1
@dwjv ในตัวอย่างแรกผู้ใช้ 3 มีทั้งที่ชอบและไม่ชอบโพสต์
Dan Henderson

คำตอบ:


20

ปัญหาที่คุณพบนั้นเรียกว่า "ฟอร์มปกติ" ของฐานข้อมูลโดยเฉพาะอย่างยิ่งฟอร์มปกติแรก https://en.wikipedia.org/wiki/First_normal_form

ฐานข้อมูลของคุณพร้อม ID ผู้ใช้ที่ต่อกัน (รุ่นแรก) ไม่ได้อยู่ในรูปแบบปกติครั้งแรก

ดูhttps://en.wikipedia.org/wiki/Database_normalizationสำหรับสาเหตุและวิธีการปรับสภาพทั่วไปให้ดี

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

เรื่องฐานข้อมูลหนัก

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

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

ปัญหาต่อไปคือความสามารถในการอ่านและการบำรุงรักษา

ตัวอย่างเช่นบอกฉันว่าข้อความทั้งสองนี้ทำอะไร:

select count(*)
from posts
inner join likes on posts.postid = likes.postid
where postid = 7

select len(likes) - len(replace(likes, ',', ''))
from posts
where postid = 7

อย่างที่ฉันได้พูดไปแล้วถ้าหาก crores หรือชอบพันล้านปรากฏบนโต๊ะ มันจะไม่ใช้เวลามากสำหรับการค้นหาตารางที่มี crores บันทึกเนื่องจากตารางจะเต็มเร็วมาก?
Harshit Shrivastava

6
@HarshitShrivastava mysql สามารถจัดการกับตารางที่เรียบง่ายเป็นพันล้านแถว แต่ลองนึกภาพคนจำนวนพันล้าน (dis) ที่ชอบเป็นสตริงในตารางผู้ใช้ของคุณ - ซึ่งอาจยิ่งใหญ่กว่าและยากที่จะทำงานด้วย
jkavalik

3
สิ่งหนึ่งที่ @til_b ไม่ได้กล่าวถึงโดยตรง (แต่โดยทั่วไปจะบอกเป็นนัยผ่านการใช้แบบฟอร์มปกติ) คือการออกแบบที่สองซึ่งถูกนำมาใช้อย่างเหมาะสมจะช่วยให้เอ็นจิ้นฐานข้อมูลต้นแบบสามารถรักษา Referential Integrity ซึ่งไม่สามารถทำได้ด้วยรูปแบบการออกแบบแรก นั่นหมายความว่าหากผู้ใช้ 4 ถูกลบฐานข้อมูลจะล้างข้อมูลที่เชื่อมโยงเพราะรู้ว่าระเบียนใดขึ้นอยู่กับบันทึกของผู้ใช้ 4 การออกแบบแรกไม่สามารถทำได้เนื่องจากฐานข้อมูลไม่ทราบวิธีการจัดการความสัมพันธ์ในสตริง
David Antaramian

9

วิธีที่สองนั้นดีกว่ามากเพราะคุณสามารถเพิ่มหรือลบ like / dislike ได้อย่างง่ายดาย

แต่คุณควรแก้ไขโซลูชันที่สองของคุณโดยใช้หนึ่งตารางสำหรับชอบหรือไม่ชอบ
คอลัมน์ของตาราง like / dislike ควรเป็น id, postid, userid และอีกอันหนึ่งสำหรับค่า like หรือ dislike เช่น 1 สำหรับ dislike และ -1 สำหรับ like

ตั้ง post_id และ user_id เป็นคีย์หลักแบบคอมโพสิตและทำงานได้ดี

ขนาดของตารางจะเพิ่มขึ้นตามกาลเวลา แต่คุณมีคอลัมน์จริงเพียงสองคอลัมน์เท่านั้น id และค่าของ like / dislike postid และ userid จะเชื่อมโยงกับมันเท่านั้นและเก็บไว้ในผู้ใช้และตารางโพสต์ของคุณ


3
คุณควรจะมีuser_id, post_idและvalueในตาราง ไม่จำเป็นต้องแยกidคอลัมน์
jkavalik

3
ตามที่ความเห็นของ @ jkavalik เกี่ยวกับคำถามที่แนะนำ 1 และ -1 น่าจะเป็นค่าที่ดีกว่าสำหรับชอบและไม่ชอบมากกว่า 1 และ 2 เพราะมันจะช่วยให้การคำนวณคะแนนรวมด้วยวิธีการรวมตารางอย่างง่ายแทนที่จะลบจำนวนของ แถวที่มี "2" จากจำนวนแถวที่มี "1"
Dan Henderson

@DanHenderson: สิ่งที่ชอบ - ไม่ชอบอาจจะเร็วกว่าผลรวมเล็กน้อย (ที่กล่าวว่าแม้ว่ามันจะทำงานกับ 1 และ -1.)
cHao

upvoted, คุณจะทำอย่างไรถ้าคุณพูดอีก 2 การกระทำเช่นความรักและความโกรธ? ฉันหมายถึง 1 สำหรับชอบและ -1 สำหรับไม่ชอบกับอีก 2 กิจกรรม
PirateApp

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