Bagaimana Anda melacak hubungan rekaman di NoSQL?

117

Saya mencoba mencari tahu padanan kunci asing dan indeks di database NoSQL KVP atau Dokumen. Karena tidak ada tabel penting (untuk menambahkan kunci yang menandai hubungan antara dua objek) saya benar-benar bingung tentang bagaimana Anda bisa mengambil data dengan cara yang akan berguna untuk halaman web normal.

Katakanlah saya memiliki pengguna, dan pengguna ini meninggalkan banyak komentar di seluruh situs. Satu-satunya cara yang dapat saya pikirkan untuk melacak komentar pengguna itu adalah dengan

  1. Sematkan mereka di objek pengguna (yang tampaknya sangat tidak berguna)
  2. Buat dan pertahankan user_id:commentsnilai yang berisi daftar kunci setiap komentar [komentar: 34, komentar: 197, dll ...] sehingga saya dapat mengambilnya sesuai kebutuhan.

Namun, mengambil contoh kedua Anda akan segera menemui jalan buntu ketika Anda menggunakannya untuk melacak hal-hal lain seperti kunci yang disebut "active_comments" yang mungkin berisi 30 juta id di dalamnya sehingga memerlukan biaya TON untuk menanyakan setiap halaman hanya untuk mengetahui beberapa yang terbaru komentar aktif. Ini juga akan sangat rentan terhadap kondisi balapan karena banyak halaman mungkin mencoba memperbaruinya pada saat yang bersamaan.

Bagaimana cara melacak relasi seperti berikut dalam database NoSQL?

  • Semua komentar pengguna
  • Semua komentar aktif
  • Semua posting diberi tag dengan [kata kunci]
  • Semua siswa di klub - atau semua klub tempat siswa berada

Atau apakah saya memikirkan hal ini dengan tidak benar?

Xeoncross
sumber
Tidak ada satu cara untuk melakukannya di database NoSQL, pertanyaan ini agak mirip dengan menanyakan bagaimana cara melacak relasi dalam program C.
stonemetal
3
Wow, kalau begitu saya kira hype tentang NoSQL menggantikan RDBMS tidak mungkin.
Xeoncross
11
Ya, NoSQL pasti overhyped. Saya tidak mengatakan bahwa teknologi baru tidak berguna dalam situasi yang tepat, tetapi konyol untuk berpikir bahwa mereka akan menggantikan RDBMS. Lihat en.wikipedia.org/wiki/Hype_cycle
Bill Karwin
1
Bukankah Anda hanya memiliki kumpulan 'pengguna' dan kumpulan komentar. Dan kemudian, setiap komentar hanya sebagai properti 'penulis' yang nilainya adalah referensi kembali ke id pengguna?
CodeFinity

Jawaban:

186

Semua jawaban tentang cara menyimpan asosiasi banyak ke banyak dengan "cara NoSQL" direduksi menjadi hal yang sama: menyimpan data secara berlebihan.

Di NoSQL, Anda tidak mendesain database Anda berdasarkan hubungan antara entitas data. Anda mendesain database Anda berdasarkan kueri yang akan Anda jalankan terhadapnya. Gunakan kriteria yang sama yang akan Anda gunakan untuk mendenormalisasi database relasional: jika lebih penting bagi data untuk memiliki kohesi (pikirkan nilai dalam daftar yang dipisahkan koma dan bukan tabel yang dinormalisasi), lakukan seperti itu.

Tapi ini pasti mengoptimalkan satu jenis kueri (misalnya komentar oleh pengguna mana pun untuk artikel tertentu) dengan mengorbankan jenis kueri lain (komentar untuk artikel apa pun oleh pengguna tertentu). Jika aplikasi Anda memiliki kebutuhan agar kedua jenis kueri tersebut dioptimalkan secara sama, Anda tidak boleh melakukan denormalisasi. Dan juga, Anda tidak boleh menggunakan solusi NoSQL jika Anda perlu menggunakan data secara relasional.

Terdapat risiko denormalisasi dan redundansi bahwa kumpulan data yang berlebihan akan tidak sinkron satu sama lain. Ini disebut anomali . Ketika Anda menggunakan database relasional yang dinormalisasi, RDBMS dapat mencegah anomali. Dalam database yang didenormalisasi atau di NoSQL, Anda bertanggung jawab untuk menulis kode aplikasi untuk mencegah anomali.

Orang mungkin berpikir bahwa akan sangat bagus untuk database NoSQL untuk melakukan kerja keras mencegah anomali untuk Anda. Ada paradigma yang bisa melakukan ini - paradigma relasional.

Bill Karwin
sumber
20
"Anda tidak boleh menggunakan solusi NoSQL jika Anda perlu menggunakan data dengan cara relasional" - Jadi bagaimana orang lain yang menjalankan NoSQL bisa lolos? Bagaimana Anda bisa mengetahui semua cara Anda akan meminta data saat pertama kali merancang aplikasi Anda? Contoh Fox, saya mungkin ingin komentar terbaru, komentar pengguna, komentar berdasarkan tag, komentar untuk posting tertentu, komentar ditandai sebagai spam, komentar aktif, komentar berperingkat tertinggi, dll.
Xeoncross
14
Persis - tidak ada yang namanya "berfungsi" seperti yang diklaim oleh para pendukung NoSQL. Entah Anda melakukan banyak analisis di depan untuk pemodelan data relasional Anda, atau Anda melakukan banyak analisis di depan untuk kueri prioritas utama Anda, atau Anda melakukan banyak refactoring yang mahal di seluruh proyek saat Anda menemukan bagian mana dari desain Anda tidak mendapatkan cukup analisis di awal.
Bill Karwin
1
Jika kami menyimpan data secara berlebihan, bagaimana kami harus memperbarui? Misalnya, mengganti namanya, dan dia menulis beberapa komentar. Namanya sudah diubah di koleksi pengguna, tetapi bagaimana cara mengubah semua nama yang disimpan secara berlebihan di koleksi komentar?
Mohammad Kermani
3
@ M98, Ah, Anda telah menemukan kelemahan dalam strategi ini. Anda harus tahu tentang semua tempat yang perlu Anda perbarui, dan kemudian menulis kode di aplikasi Anda untuk memperbarui semuanya ketika Anda memperbarui salah satu. Semoga berhasil!
Bill Karwin
2
Masalah yang sama ada untuk database relasional yang didenormalisasi .
Bill Karwin
5

Pendekatan couchDB menyarankan untuk mengeluarkan kelas barang yang tepat dalam fase peta dan meringkasnya dalam pengurangan .. Jadi Anda bisa memetakan semua komentar dan mengeluarkan 1untuk pengguna tertentu dan kemudian mencetak hanya satu. Ini akan membutuhkan banyak penyimpanan disk untuk membangun tampilan persisten dari semua data yang dapat dilacak di couchDB. btw mereka juga memiliki halaman wiki ini tentang hubungan: http://wiki.apache.org/couchdb/EntityRelationship .

Riak sebaliknya memiliki alat untuk membangun relasi. Itu adalah tautan. Anda dapat memasukkan alamat dokumen yang ditautkan (di sini komentar) ke dokumen 'root' (di sini dokumen pengguna). Ini memiliki satu trik. Jika didistribusikan, itu dapat diubah pada satu waktu di banyak lokasi. Ini akan menyebabkan konflik dan akibatnya pohon jam vektor besar: / ..tidak terlalu buruk, tidak terlalu baik.

Riak juga memiliki 'mekanisme' lain. Ini memiliki ruang nama kunci 2-lapisan, yang disebut ember dan kunci. Jadi, misalnya siswa, Jika kita memiliki klub A, B dan C dan siswa StudentX, StudentY Anda dapat mempertahankan ketentuan berikut:

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

dan untuk membaca relasi cukup cantumkan kunci dalam wadah yang diberikan. Apa yang salah dengan itu? Ini sangat lambat. Mencantumkan ember tidak pernah menjadi prioritas untuk riak. Ini menjadi lebih baik dan lebih baik lagi. btw. Anda tidak membuang-buang memori karena contoh ini {true}dapat ditautkan ke satu profil lengkap StudentX atau Y (di sini konflik tidak dimungkinkan).

Seperti yang Anda lihat, NoSQL! = NoSQL. Anda perlu melihat implementasi spesifik dan mengujinya sendiri.

Disebutkan sebelumnya Column store terlihat cocok untuk relasi .. tapi itu semua tergantung pada kebutuhan A dan C dan P Anda;) Jika Anda tidak membutuhkan A dan Anda memiliki kurang dari Peta byte biarkan saja, lanjutkan dengan MySql atau Postgres.

semoga berhasil

pengguna425720
sumber
1
Riak baru-baru ini merilis v1.0, yang menambahkan dukungan untuk indeks sekunder saat menggunakan backend LevelDB. Fitur yang sangat berharga.
Jon L.
4
  1. user: userid: comments adalah pendekatan yang masuk akal - anggap saja itu setara dengan indeks kolom dalam SQL, dengan persyaratan tambahan bahwa Anda tidak dapat melakukan kueri pada kolom yang tidak terindeks.

  2. Di sinilah Anda perlu memikirkan kebutuhan Anda. Daftar dengan 30 juta item bukannya tidak masuk akal karena lambat, tetapi karena tidak praktis untuk melakukan apa pun dengannya. Jika kebutuhan Anda yang sebenarnya adalah untuk menampilkan beberapa komentar terbaru, Anda lebih baik menyimpan daftar yang sangat pendek yang diperbarui setiap kali komentar ditambahkan - ingat bahwa NoSQL tidak memiliki persyaratan normalisasi. Kondisi balapan adalah masalah dengan daftar di penyimpanan nilai kunci dasar tetapi umumnya platform Anda mendukung daftar dengan benar, Anda dapat melakukan sesuatu dengan kunci, atau Anda tidak benar-benar peduli dengan pembaruan yang gagal.

  3. Sama seperti untuk komentar pengguna - buat kata kunci indeks: posting

  4. Lebih mirip - mungkin daftar klub sebagai properti siswa dan indeks di bidang itu untuk mendapatkan semua anggota klub

Tom Clarkson
sumber
Jadi, pada dasarnya semuanya hanya butuh daftar? Sepertinya harus ada pendekatan yang lebih canggih dari sekedar melacak string id secara manual. Pertama, Anda hanya bisa melangkah sejauh itu sebelum mereka menjadi besar untuk berguna. Kemudian lagi, proyek poster-child utama dari teknologi NoSQL (MongoDB, CouchDB, Membase, dll) adalah semua proyek baru jadi mungkin saya hanya perlu memberi mereka lebih banyak waktu untuk menemukan cara yang lebih baik untuk melacak hubungan.
Xeoncross
Jika Anda menggunakan NoSQL (AKA non-relational data store), Anda harus berhenti berpikir dalam istilah relasional. Pendekatan yang digunakan akan berbeda antar platform, tetapi gagasan dasar bahwa Anda harus mengelola indeks cukup universal. Contoh hubungan yang telah Anda berikan dimodelkan dalam dua cara berbeda di NoSQL: 1) Penyimpanan - tidak seperti SQL, kolom dapat memiliki banyak nilai / kompleks, jadi objek turunan hanyalah bagian dari objek induk. 2) Pencarian - Daftar panjang Anda sebenarnya merupakan persyaratan untuk dapat dicari, yang berarti pengindeksan - Anda dapat menggunakan daftar kustom sederhana atau mesin pencari yang lebih lengkap.
Tom Clarkson
2

Kamu punya

"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"]
}

Dalam database relasional, hal yang biasa dilakukan dalam relasi satu-ke-banyak adalah menormalkan data. Itu adalah hal yang sama yang akan Anda lakukan di database NoSQL juga. Cukup indeks bidang yang akan Anda ambil informasinya.

Misalnya, indeks penting untuk Anda adalah

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

Jika Anda menggunakan NosDB (Basis Data NoSQL berbasis .NET dengan dukungan SQL) kueri Anda akan seperti ini

 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'

Periksa semua jenis kueri yang didukung dari lembar contekan atau dokumentasinya SQL .

Basit Anwer
sumber