Desain Skema MongoDB - Banyak dokumen kecil atau lebih sedikit dokumen besar?

89

Latar Belakang
Saya sedang membuat prototipe konversi dari database RDBMS kami ke MongoDB. Saat melakukan denormalisasi, sepertinya saya memiliki dua pilihan, yang satu mengarah ke banyak (jutaan) dokumen yang lebih kecil atau satu lagi yang mengarah ke lebih sedikit (ratusan ribu) dokumen besar.

Jika saya dapat menyaringnya menjadi analog sederhana, itu akan menjadi perbedaan antara koleksi dengan dokumen Pelanggan yang lebih sedikit seperti ini (di Java):

kelas Pelanggan {
    nama String pribadi;
    alamat Alamat pribadi;
    // setiap Kartu Kredit memiliki ratusan contoh Pembayaran
    Private Set <CreditCard> creditCards;
}

atau kumpulan dengan banyak, banyak dokumen pembayaran seperti ini:

class Payment {
    pelanggan pribadi Pelanggan;
    CreditCard CreditCard pribadi;
    Private Date payDate;
    private float payAmount;
}

Pertanyaan
Apakah MongoDB dirancang untuk lebih menyukai banyak, banyak dokumen kecil atau lebih sedikit dokumen besar? Apakah jawabannya sebagian besar bergantung pada kueri apa yang saya rencanakan untuk dijalankan? (mis. Berapa banyak kartu kredit yang dimiliki pelanggan X? vs Berapa jumlah rata-rata yang dibayar semua pelanggan bulan lalu?)

Saya telah melihat-lihat banyak tetapi saya tidak menemukan praktik terbaik skema MongoDB yang akan membantu saya menjawab pertanyaan saya.

Andre
sumber

Jawaban:

82

Anda pasti perlu mengoptimalkan kueri yang Anda lakukan.

Ini tebakan terbaik saya berdasarkan deskripsi Anda.

Anda mungkin ingin mengetahui semua Kartu Kredit untuk setiap Pelanggan, jadi simpanlah semua itu di dalam Objek Pelanggan. Anda juga mungkin ingin memiliki referensi Pelanggan untuk setiap Pembayaran. Ini akan membuat dokumen Pembayaran relatif kecil.

Objek Pembayaran secara otomatis akan memiliki ID dan indeksnya sendiri. Anda mungkin ingin menambahkan indeks pada referensi Pelanggan juga.

Ini akan memungkinkan Anda untuk mencari Pembayaran oleh Pelanggan dengan cepat tanpa menyimpan seluruh objek pelanggan setiap saat.

Jika Anda ingin menjawab pertanyaan seperti "Berapa jumlah rata-rata yang dibayar semua pelanggan bulan lalu" Anda akan menginginkan peta / pengurangan untuk set data yang cukup besar. Anda tidak mendapatkan tanggapan ini "waktu nyata". Anda akan menemukan bahwa menyimpan "referensi" untuk Pelanggan mungkin cukup baik untuk pengurangan peta ini.

Jadi untuk menjawab pertanyaan Anda secara langsung: Apakah MongoDB dirancang untuk lebih menyukai banyak, banyak dokumen kecil atau lebih sedikit dokumen besar?

MongoDB dirancang untuk menemukan entri yang diindeks dengan sangat cepat. MongoDB sangat pandai menemukan beberapa jarum di tumpukan jerami yang besar. MongoDB tidak pandai menemukan sebagian besar jarum di tumpukan jerami. Jadi, buat data Anda berdasarkan kasus penggunaan yang paling umum dan tulis peta / kurangi tugas untuk kasus penggunaan yang lebih jarang.

Gates VP
sumber
32

Menurut dokumentasi MongoDB sendiri, sepertinya itu dirancang untuk banyak dokumen kecil.

Dari Praktik Terbaik Kinerja untuk MongoDB :

Ukuran maksimum dokumen di MongoDB adalah 16 MB. Dalam praktiknya, sebagian besar dokumen berukuran beberapa kilobyte atau kurang. Pertimbangkan dokumen lebih seperti baris dalam tabel daripada tabel itu sendiri. Daripada mempertahankan daftar rekaman dalam satu dokumen, jadikan setiap rekaman sebagai dokumen.

Dari 6 Aturan Thumb untuk Desain Skema MongoDB: Bagian 1 :

Pemodelan Satu-ke-Beberapa

Contoh "satu-ke-sedikit" mungkin alamat untuk seseorang. Ini adalah kasus penggunaan yang baik untuk penyematan - Anda akan meletakkan alamat dalam larik di dalam objek Person Anda.

Satu-ke-Banyak

Contoh dari "satu-ke-banyak" mungkin adalah suku cadang untuk produk dalam sistem pemesanan suku cadang pengganti. Setiap produk dapat memiliki hingga beberapa ratus suku cadang, tetapi tidak pernah lebih dari beberapa ribu atau lebih. Ini adalah kasus penggunaan yang baik untuk referensi - Anda akan meletakkan ObjectIDs dari bagian-bagian dalam larik di dokumen produk.

Satu-ke-Squillions

Contoh "satu-ke-squillions" mungkin adalah sistem pencatatan peristiwa yang mengumpulkan pesan log untuk mesin yang berbeda. Setiap host yang diberikan dapat menghasilkan pesan yang cukup untuk melebihi ukuran dokumen 16 MB, bahkan jika semua yang Anda simpan dalam larik adalah ObjectID. Ini adalah kasus penggunaan klasik untuk "referensi orang tua" - Anda akan memiliki dokumen untuk host, dan kemudian menyimpan ObjectID dari host di dokumen untuk pesan log.

bmaupin
sumber
13

Dokumen yang tumbuh secara substansial dari waktu ke waktu dapat menjadi bom waktu. Bandwidth jaringan dan penggunaan RAM kemungkinan akan menjadi hambatan yang dapat diukur, memaksa Anda untuk memulai kembali.

Pertama, mari pertimbangkan dua koleksi: Pelanggan dan Pembayaran. Jadi, jumlahnya cukup kecil: satu dokumen per pembayaran.

Selanjutnya Anda harus memutuskan bagaimana memodelkan informasi akun, seperti kartu kredit. Mari pertimbangkan apakah dokumen pelanggan berisi rangkaian informasi akun atau apakah Anda memerlukan koleksi Akun baru.

Jika dokumen akun terpisah dari dokumen pelanggan, memuat semua akun untuk satu pelanggan ke dalam memori memerlukan pengambilan beberapa dokumen. Itu mungkin diterjemahkan ke dalam memori ekstra, I / O, bandwidth, dan penggunaan CPU. Apakah itu berarti bahwa pengumpulan Akun adalah ide yang buruk?

Keputusan Anda memengaruhi dokumen pembayaran. Jika informasi akun disematkan dalam dokumen pelanggan, bagaimana Anda akan mereferensikannya? Dokumen akun terpisah memiliki atribut _id-nya sendiri. Dengan informasi akun yang disematkan, aplikasi Anda akan menghasilkan id baru untuk akun atau menggunakan atribut akun (mis., Nomor akun) untuk kuncinya.

Mungkinkah dokumen pembayaran benar-benar berisi semua pembayaran yang dilakukan dalam jangka waktu tetap (misalnya, hari?). Kompleksitas seperti itu akan mempengaruhi semua kode yang membaca dan menulis dokumen pembayaran. Pengoptimalan prematur bisa mematikan proyek.

Seperti dokumen akun, pembayaran dengan mudah dirujuk selama dokumen pembayaran hanya berisi satu pembayaran. Jenis dokumen baru, kredit misalnya, dapat merujuk pada pembayaran. Tetapi apakah Anda akan membuat koleksi Kredit atau akankah Anda menyematkan informasi kredit di dalam informasi pembayaran? Apa yang akan terjadi jika nanti Anda perlu mereferensikan kredit?

Ringkasnya, saya telah sukses dengan banyak dokumen kecil dan banyak koleksi. Saya mengimplementasikan referensi dengan _id dan hanya dengan _id. Oleh karena itu, saya tidak khawatir tentang dokumen yang terus berkembang menghancurkan aplikasi saya. Skema ini mudah dipahami dan diindeks karena setiap entitas memiliki koleksinya sendiri. Entitas penting tidak bersembunyi di dalam dokumen lain.

Saya ingin mendengar tentang temuan Anda. Semoga berhasil!

Terris
sumber