การใช้ข้อคิดเห็นและไลค์ในฐานข้อมูล


146

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

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

ฉันพบคำถามที่คล้ายกันที่นี่ แต่ไม่มีคำตอบที่น่าพอใจดังนั้นฉันจึงถามคำถามนี้อีกครั้ง

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

รายละเอียด : ฉันมีตาราง Userที่มีข้อมูลของผู้ใช้บางส่วนและอีก 3 ตาราง : Photoกับการถ่ายภาพ , Articlesกับบทความ , Placesกับสถานที่ ฉันต้องการเปิดใช้งานผู้ใช้ที่บันทึกไว้เพื่อ:

  • แสดงความคิดเห็นใด ๆ ใน 3 ตารางเหล่านั้น

  • ทำเครื่องหมายใด ๆ ของพวกเขาเป็นที่ชอบ

  • ติดแท็กใด ๆ ของพวกเขาด้วยแท็กบางอย่าง

  • ฉันต้องการนับจำนวนไลค์สำหรับทุกองค์ประกอบและจำนวนครั้งที่ใช้แท็กเฉพาะ

1 เซนต์วิธีการ :

a) สำหรับแท็กฉันจะสร้างตาราง Tag [TagId, tagName, tagCounter]แล้วฉันจะสร้างหลายต่อหลายความสัมพันธ์ตารางสำหรับ: Photo_has_tags, ,Place_has_tagArticle_has_tag

b) จำนวนเดียวกันสำหรับความคิดเห็น

c) ฉันจะสร้างตาราง LikedPhotos [idUser, idPhoto] , ,LikedArticles[idUser, idArticle] LikedPlace [idUser, idPlace]จำนวนรายการที่ชอบจะถูกคำนวณโดยข้อความค้นหา (ซึ่งฉันถือว่าไม่ดี) และ...

ฉันไม่ชอบการออกแบบนี้ในส่วนสุดท้ายมีกลิ่นไม่ดีสำหรับฉัน;)


2 ครั้งวิธีการ :

ผมจะสร้างตารางElementType [idType, TypeName == some table name]ซึ่งจะมีประชากรโดยผู้ดูแลระบบ (ฉัน) ที่มีชื่อของตารางที่สามารถชอบ , แสดงความคิดเห็นหรือแท็ก จากนั้นฉันจะสร้างตาราง :

ก) LikedElement [idLike, idUser, idElementType, idLikedElement]และเช่นเดียวกันสำหรับความคิดเห็นและแท็กที่มีคอลัมน์ที่เหมาะสมสำหรับแต่ละรายการ ตอนนี้เมื่อฉันต้องการทำให้ภาพที่ชอบฉันจะแทรก:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

และสำหรับสถานที่:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

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

ในที่สุดฉันก็สงสัยว่าสถานที่ที่ดีที่สุดในการจัดเก็บเคาน์เตอร์สำหรับองค์ประกอบที่ชอบคือเท่าไหร่ ฉันนึกได้สองวิธีเท่านั้น:

  1. ในองค์ประกอบ ( Photo/Article/Place) ตาราง
  2. โดยเลือกจำนวน ()

ฉันหวังว่าคำอธิบายปัญหาของฉันจะละเอียดยิ่งขึ้นในขณะนี้


คุณพิจารณา XML แล้วหรือยัง
CodyBugstein

1
ฉันไม่ค่อยพบคำถามเช่นนี้ที่เป็น 100% สิ่งที่ฉันมีในใจคำถามของคุณเสร็จสมบูรณ์สุดยอด! ขอบคุณ @Kokos
aderchox

คำตอบ:


195

โซลูชันที่ขยายได้มากที่สุดคือการมีตาราง "ฐาน" เพียงอันเดียว (เชื่อมต่อกับ "ไลค์" แท็กและความคิดเห็น) และ "สืบทอด" ตารางอื่น ๆ ทั้งหมดจากตาราง การเพิ่มเอนทิตีแบบใหม่เกี่ยวข้องกับการเพิ่มตาราง "ที่สืบทอดมา" ใหม่ - จากนั้นจะเสียบเข้ากับเครื่องจักร like / tag / comment ทั้งหมดโดยอัตโนมัติ

คำความสัมพันธ์เอนทิตีสำหรับสิ่งนี้คือ "หมวดหมู่" (ดู คู่มือวิธีการของ ERwin , หัวข้อ: "ความสัมพันธ์ย่อย") สัญลักษณ์หมวดหมู่คือ:

ประเภท

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

แผนภาพ ER


BTW มีประมาณ 3 วิธีในการใช้ "หมวดหมู่ ER":

  • ทุกประเภทในหนึ่งตาราง
  • คอนกรีตทุกประเภทในตารางแยกต่างหาก
  • คอนกรีตและนามธรรมทุกประเภทแยกเป็นตาราง

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


2
คำตอบที่ดีขอบคุณ ฉันหวังว่าฉันจะจัดการเพื่อใช้มัน ... และฉันสงสัยว่า Django ORM จะจัดการกับแผนที่ได้อย่างไร (หรือฉันจะทำด้วยตัวเองได้อย่างไร ... แต่นั่นคือปัญหาอื่น;)) แต่คุณช่วยอธิบายได้ไหม ฉันเพราะฉันคิดว่าฉันไม่เข้าใจอย่างถูกต้อง - สิ่งที่คุณวาดให้ฉัน (ขอบคุณ!) เป็นวิธีที่สามที่คุณพูดถึง?
Kokos

2
@Kokos โดยพื้นฐานแล้ววิธีการ (3) หมายความว่า ENTITY เป็นตาราง PHOTO เป็นตาราง ARTICLE เป็นตารางและ PLACE เป็นตาราง วิธีการ (2) จะหมายถึงไม่มีตารางสำหรับ ENTITY และวิธีการ (1) จะหมายถึงมีเพียงหนึ่งตาราง การดำรงอยู่ของวิธีการเหล่านี้ทั้งหมด (ทั้งหมดที่มีจุดแข็งและจุดอ่อนของพวกเขา) เป็นผลมาจากโชคร้ายที่ความจริงที่ว่า RDBMS ทั่วไปไม่สนับสนุนการสืบทอดตารางโดยกำเนิด
Branko Dimitrijevic

1
+1 ขอบคุณสำหรับคำอธิบายและการอ้างอิงที่ดีเกี่ยวกับ "หมวดหมู่" ฉันกำลังจะโพสต์คำถามใกล้กับสิ่งนี้ แต่คุณตอบคำถามได้ที่นี่
andy holaday

2
@BrankoDimitrijevic ทำไมตารางเอนทิตีภาพถ่าย, บทความ, สถานที่มี PK ของตัวเองไม่ได้เช่น PhotoID, ArticleID ฯลฯ แต่ยังมีอีกคอลัมน์หนึ่งสำหรับ Entity_ID เป็น FK มันไม่จำเป็นเหรอ?
เล่มที่

3
@Orion ค่าสูงสุดBIGINTคือ 9223372036854775807 ถ้าคุณใส่หนึ่งแถวในแต่ละวินาทีคุณจะหมดค่าที่มีอยู่ในประมาณ 300 ล้านปี แน่นอนว่าคุณจะสามารถพอร์ตไปยังจำนวนเต็ม 128 บิตในเวลานั้น!
Branko Dimitrijevic

22

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

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

หากนี่เป็นโครงการเดียวให้ตั้งค่าอินเทอร์เฟซฐานข้อมูลลงในการดำเนินการอย่างง่ายโดยใช้โพรซีเดอร์ที่เก็บไว้: add_user, update_user, add_comment, add_like, upload_photo, list_comments ฯลฯ อย่าฝังสคีมาลงในโค้ดแม้แต่บรรทัดเดียว ด้วยวิธีนี้สกีมาฐานข้อมูลสามารถเปลี่ยนแปลงได้โดยไม่ส่งผลกระทบต่อโค้ดใด ๆ : เฉพาะขั้นตอนการจัดเก็บที่ควรทราบเกี่ยวกับสกีมา

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


2
เพราะฉันต้องใช้มันด้วยตัวเอง อย่างน้อยตอนนี้ ... และฉันคิดว่าอาจเป็นโอกาสที่ดีที่จะเริ่มชอบฐานข้อมูลสักหน่อย;) ขอบคุณสำหรับคำแนะนำของคุณเกี่ยวกับขั้นตอนการจัดเก็บ มีคนรู้ไหมว่าถ้าพวกเขาถูกแมปโดย Django ORM โดยอัตโนมัติ?
Kokos

6
ฉันรักประโยคสุดท้ายของคุณ - มันดีกว่าครั้งที่สองเสมอ
ลูอิส

2
มันจะดีกว่าเสมอในครั้งที่สอง Yup
เล่นเกม

20

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

ป้อนคำอธิบายรูปภาพที่นี่

pseudocode นี้จะได้รับความคิดเห็นทั้งหมดของภาพถ่ายด้วย ID 5
SELECT * จากการกระทำ
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "ภาพถ่าย"
และ actions.typeAction = "ความคิดเห็น"

รหัสเทียมนี้จะได้รับไลค์ทั้งหมดหรือผู้ใช้ที่ชอบรูปภาพที่มี ID 5
(คุณอาจใช้จำนวน () เพื่อรับจำนวนไลค์)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"  

ฉันคิดว่าคุณอาจชอบความคิดเห็นเช่นเดียวกับการคลิกลิงก์ "ชอบ" ในความคิดเห็น แบบสอบถามนี้จะได้รับความชอบของความคิดเห็น (การกระทำ) ด้วย ID 133: SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
964260

1
ฉันจะจำโซลูชันนี้ได้อย่างแน่นอนสำหรับการเผยแพร่ระบบของฉันเพิ่มเติม :)
Kokos

ฉันมีสิ่ง 2 รายการ stuff1 และ stuff2 ... ฉันตามแผนภาพนี้ แต่มีข้อผิดพลาด sql ขณะใช้สิ่งนี้ ... stuff1, stuff2 เป็นสองตารางอิสระที่มีคีย์หลักอิสระและตารางการกระทำมีคอลัมน์ id_stuff ซึ่งอ้างอิงถึง สองแท็บเหล่านี้คือ stuff1, stuff2 ตัวอย่างเช่น stuff1 มี 5 แถว, stuff2 มี 10 แถว, เมื่อฉันพยายามเพิ่มแถวในตารางการกระทำที่มี id_stuff อะไรที่น้อยกว่า 5 ให้พูดว่า '3' มันประมวลผลแบบสอบถามเพราะมีแถวที่มี id_stuff '3' ทั้งใน stuff1 และ stuff2 แต่ถ้าฉันพยายามที่จะเพิ่มแถวที่มี id_stuff มากกว่า 5 ... (ยังคงความคิดเห็นต่อไป)
vikas devde

1
หากมีการใช้ไลค์แบบนี้มันจะทำให้การแจ้งเตือนผู้ใช้ไลค์ใหม่นั้นยากขึ้น มันจะต้องมีตารางอื่น
Greg L

4
วิธีการที่จะid_stuffคอลัมน์ประกอบด้วยค่าที่ไม่ซ้ำกันในแต่ละสามตาราง?
เล่มที่ 1

0

เท่าที่ฉันเข้าใจ. ต้องใช้หลายตาราง มีความสัมพันธ์ระหว่างพวกเขากับคนมากมาย

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

ถ้าคุณโพสต์แผนภาพฐานข้อมูลของคุณ ฉันสามารถวาดความสัมพันธ์
erencan

0

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

ถ้าไม่ชอบคนที่ต้องใช้ตารางน้อยลง

ในกรณีนี้:

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

ฉันคิดว่าวิธี "เลือกปฏิบัติ" ของคุณตัวเลือกที่ 2 ให้ผลการสืบค้นที่ง่ายกว่าในบางกรณีและดูเหมือนจะไม่แย่กว่านั้นในกรณีอื่น ๆ ดังนั้นฉันจะไปด้วย


0

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


-1

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

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

ตารางขนาดใหญ่หนึ่งตารางที่มีพจนานุกรมอาจไม่สามารถควบคุมได้ในหนึ่งวัน


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