คุณติดตามบันทึกความสัมพันธ์ใน NoSQL ได้อย่างไร?


118

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

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

  1. ฝังไว้ในวัตถุผู้ใช้ (ซึ่งดูเหมือนไม่มีประโยชน์เลย)
  2. สร้างและรักษาuser_id:commentsค่าที่มีรายการคีย์ของแต่ละความคิดเห็น [ความคิดเห็น: 34, ความคิดเห็น: 197 ฯลฯ ... ] เพื่อให้ฉันสามารถดึงข้อมูลได้ตามต้องการ

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

ฉันจะติดตามความสัมพันธ์ดังต่อไปนี้ในฐานข้อมูล NoSQL ได้อย่างไร

  • ความคิดเห็นทั้งหมดของผู้ใช้
  • ความคิดเห็นที่ใช้งานอยู่ทั้งหมด
  • โพสต์ทั้งหมดที่ติดแท็ก [คีย์เวิร์ด]
  • นักเรียนทุกคนในชมรม - หรือทุกชมรมที่นักเรียนอยู่

หรือฉันคิดเรื่องนี้ไม่ถูกต้อง?


ไม่มีวิธีใดวิธีหนึ่งที่จะทำได้ในฐานข้อมูล NoSQL คำถามนี้ค่อนข้างเกี่ยวข้องกับการถามว่าฉันจะติดตามความสัมพันธ์ในโปรแกรม C ได้อย่างไร
stonemetal

3
ว้าวฉันเดาว่าโฆษณาเกี่ยวกับ NoSQL แทนที่ RDBMS เป็นไปไม่ได้
Xeoncross

11
ใช่ NoSQL ถูกพิมพ์มากเกินไป ฉันไม่ได้บอกว่าเทคโนโลยีใหม่ ๆ ไม่มีประโยชน์ในสถานการณ์ที่ถูกต้อง แต่มันไร้สาระที่คิดว่ามันจะมาแทนที่ RDBMS ดูen.wikipedia.org/wiki/Hype_cycle
Bill Karwin

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

คำตอบ:


187

คำตอบทั้งหมดสำหรับวิธีจัดเก็บการเชื่อมโยงแบบกลุ่มต่อกลุ่มใน "วิธี NoSQL" ลดลงเป็นสิ่งเดียวกันนั่นคือการจัดเก็บข้อมูลซ้ำซ้อน

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

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

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

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


20
"คุณไม่ควรใช้โซลูชัน NoSQL หากคุณต้องการใช้ข้อมูลในเชิงสัมพันธ์" - แล้วคนอื่น ๆ ที่ใช้ NoSQL จะหนีไปได้อย่างไร? คุณจะรู้วิธีทั้งหมดที่คุณจะค้นหาข้อมูลเมื่อคุณออกแบบแอปพลิเคชันครั้งแรกได้อย่างไร ตัวอย่างเช่น Fox ฉันอาจต้องการความคิดเห็นล่าสุดความคิดเห็นโดยผู้ใช้ความคิดเห็นตามแท็กความคิดเห็นสำหรับโพสต์ที่ระบุความคิดเห็นที่ทำเครื่องหมายว่าเป็นสแปมความคิดเห็นที่ใช้งานอยู่ความคิดเห็นที่ได้รับคะแนนสูงสุด ฯลฯ
Xeoncross

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

1
หากเราจัดเก็บข้อมูลซ้ำซ้อนเราควรปรับปรุงสิ่งต่างๆอย่างไร? ตัวอย่างเช่นเปลี่ยนชื่อและเขียนความคิดเห็น ชื่อของเขาเปลี่ยนไปแล้วในคอลเลกชันผู้ใช้ แต่จะเปลี่ยนชื่อที่เก็บซ้ำซ้อนทั้งหมดในคอลเลกชันความคิดเห็นได้อย่างไร?
Mohammad Kermani

3
@ M98 คุณพบจุดอ่อนของกลยุทธ์นี้แล้ว คุณต้องรู้เกี่ยวกับสถานที่ทั้งหมดที่คุณต้องอัปเดตจากนั้นเขียนโค้ดในแอปพลิเคชันของคุณเพื่ออัปเดตทั้งหมดเมื่อคุณอัปเดตสถานที่ใด ๆ โชคดี!
Bill Karwin

2
ปัญหาเดียวกันที่มีอยู่สำหรับdenormalizedฐานข้อมูลเชิงสัมพันธ์
Bill Karwin

5

วิธีการ couchDB แนะนำให้ปล่อยคลาสที่เหมาะสมของสิ่งต่างๆในเฟสแผนที่และสรุปแบบลด .. ดังนั้นคุณสามารถจับคู่ความคิดเห็นทั้งหมดและส่งออก1ไปยังผู้ใช้ที่ระบุและพิมพ์เฉพาะในภายหลัง อย่างไรก็ตามจะต้องใช้พื้นที่เก็บข้อมูลดิสก์จำนวนมากในการสร้างมุมมองต่อเนื่องของข้อมูลที่ติดตามได้ทั้งหมดใน couchDB btw พวกเขายังมีหน้าวิกินี้เกี่ยวกับความสัมพันธ์: http://wiki.apache.org/couchdb/EntityRelationship http://wiki.apache.org/couchdb/EntityRelationship

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

Riak ยังมี 'กลไก' อีกอย่างหนึ่ง มีช่องว่างชื่อคีย์ 2 ชั้นเรียกว่าที่เก็บข้อมูลและคีย์ ตัวอย่างเช่นนักเรียนถ้าเรามี club A, B และ C และ student StudentX, StudentY คุณสามารถรักษาแบบแผนต่อไปนี้ได้:

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

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

อย่างที่คุณเห็น NoSQL! = NoSQL คุณต้องดูการใช้งานเฉพาะและทดสอบด้วยตัวคุณเอง

พูดถึงก่อนร้านค้าคอลัมน์ดูเหมือนจะเหมาะกับความสัมพันธ์ .. แต่ทุกอย่างขึ้นอยู่กับความต้องการ A และ C และ P ของคุณ) หากคุณไม่ต้องการ A และคุณมีจำนวนน้อยกว่า Peta ไบต์เพียงแค่ปล่อยให้ใช้ MySql หรือ Postgres

โชคดี


1
Riak เพิ่งเปิดตัว v1.0 ซึ่งเพิ่มการรองรับดัชนีรองเมื่อใช้แบ็กเอนด์ LevelDB คุณสมบัติที่มีค่ามาก
Jon L.

4
  1. ผู้ใช้: userid: ความคิดเห็นเป็นวิธีการที่สมเหตุสมผล - คิดว่ามันเทียบเท่ากับดัชนีคอลัมน์ใน SQL โดยมีข้อกำหนดเพิ่มเติมที่คุณไม่สามารถสืบค้นในคอลัมน์ที่ไม่ได้จัดทำดัชนีได้

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

  3. เช่นเดียวกับความคิดเห็นของผู้ใช้ - สร้างคำหลักดัชนี: โพสต์

  4. ที่เหมือนกันมากขึ้น - อาจเป็นรายชื่อสโมสรในฐานะทรัพย์สินของนักเรียนและดัชนีในสาขานั้นเพื่อรับสมาชิกทั้งหมดของสโมสร


ดังนั้นโดยพื้นฐานแล้วทุกอย่างต้องการเพียงแค่รายการ? ดูเหมือนว่าควรมีวิธีการที่ซับซ้อนกว่าการติดตามสตริงของรหัสด้วยตนเอง ประการแรกคุณสามารถไปให้ไกลก่อนที่พวกเขาจะใหญ่เพื่อเป็นประโยชน์ จากนั้นอีกครั้งโครงการเด็กโปสเตอร์หลักของเทคโนโลยี NoSQL (MongoDB, CouchDB, Membase และอื่น ๆ ) เป็นโครงการใหม่ทั้งหมดดังนั้นบางทีฉันอาจต้องให้เวลาพวกเขามากขึ้นเพื่อหาวิธีที่ดีกว่าในการติดตามความสัมพันธ์
Xeoncross

หากคุณใช้ NoSQL (ที่เก็บข้อมูลที่ไม่ใช่เชิงสัมพันธ์ของ AKA) คุณต้องหยุดคิดในแง่เชิงสัมพันธ์ แนวทางที่ใช้จะแตกต่างกันระหว่างแพลตฟอร์ม แต่แนวคิดพื้นฐานที่คุณต้องจัดการดัชนีนั้นค่อนข้างเป็นสากล ตัวอย่างความสัมพันธ์ที่คุณให้มาจะถูกสร้างแบบจำลองในสองวิธีที่แตกต่างกันใน NoSQL: 1) พื้นที่เก็บข้อมูล - ซึ่งแตกต่างจาก SQL คอลัมน์สามารถมีค่าหลายค่า / ซับซ้อนได้ดังนั้นวัตถุลูกจึงเป็นเพียงส่วนหนึ่งของออบเจ็กต์หลัก 2) การค้นหา - รายการแบบยาวของคุณเป็นข้อกำหนดสำหรับความสามารถในการค้นหาซึ่งหมายถึงการจัดทำดัชนี - คุณสามารถใช้รายการแบบกำหนดเองที่เรียบง่ายหรือเครื่องมือค้นหาที่สมบูรณ์ยิ่งขึ้น
Tom Clarkson

2

คุณมี

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

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

ตัวอย่างเช่นดัชนีที่สำคัญสำหรับคุณคือ

  • Comment.UserID
  • Comment.PageID
  • Comment.PostTime
  • Page.Tag []

หากคุณใช้NosDB (ฐานข้อมูล NoSQL ที่ใช้A .NET พร้อมการสนับสนุน SQL) การสืบค้นของคุณจะเป็นเช่นนี้

 SELECT * FROM Comments WHERE userid = That user’;

 SELECT * FROM Comments WHERE pageid = That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

ตรวจสอบประเภทคิวรีที่รองรับทั้งหมดจากชีตหรือเอกสารประกอบของSQL

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