Memahami batas ukuran Dokumen MongoDB BSON


153

Dari MongoDB Panduan Definitif:

Dokumen yang lebih besar dari 4MB (saat dikonversi ke BSON) tidak dapat disimpan ke database. Ini adalah batas yang agak arbitrer (dan dapat dinaikkan di masa depan); sebagian besar untuk mencegah desain skema buruk dan memastikan kinerja yang konsisten.

Saya tidak mengerti batas ini, apakah ini berarti bahwa Dokumen yang berisi posting Blog dengan banyak komentar yang kebetulan lebih besar dari 4MB tidak dapat disimpan sebagai dokumen tunggal?

Apakah ini juga menghitung dokumen bersarang?

Bagaimana jika saya ingin dokumen yang mengaudit perubahan ke nilai. (Pada akhirnya akan tumbuh, melebihi batas 4MB.)

Semoga seseorang menjelaskan ini dengan benar.

Saya baru saja mulai membaca tentang MongoDB (database nosql pertama yang saya pelajari).

Terima kasih.


5
Saya pikir pertanyaannya harus menjelaskan bahwa ini adalah batasan ukuran dokumen yang disimpan MongoDB dan bukan dari format BSON.
alexpopescu

2
Padahal, saya baru saja mencoba menyimpan dokumen besar yang pastinya melebihi 4MB untuk mendapatkan pesan "BSON :: InvalidDocument: Dokumen terlalu besar: dokumen BSON terbatas pada 4194304 byte." Jika itu masalahnya, bukankah itu agak menyesatkan dalam pesan peringatan / kesalahan?
Nik So

18
Anda dapat dengan mudah menemukan ukuran dokumen BSON maks Anda dengan db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'perintah di mongoshell.
AhmetB - Google

5
apa tujuan schemaless nosql di mana Anda tidak dapat membuang catatan lebih dari 16 mb dan membangun operasi crud di atasnya!
Rizwan Patel

Saya pikir kutipan awal mengatakan itu semua ... Batasnya ada untuk mencegah desain skema yang buruk. Jika, misalnya Anda memiliki posting dengan banyak komentar, Anda ingin koleksi entri blog dan koleksi komentar, atau koleksi perubahan. Desain mongo / nosql memungkinkan untuk hal-hal berukuran besar sebagai jaringan dokumen, tetapi pengembang perlu memecahnya menjadi bagian-bagian yang masuk akal. Jika tidak ada batas ukuran yang ditetapkan, masalah lain akan terjadi. Saya pikir batas 4MB baik-baik saja. 16mb, bagus! Tetapi jika saya menulis dokumen 16MB, itu adalah petunjuk bahwa ada sesuatu yang salah dengan desainnya.
Eyelash

Jawaban:


126

Pertama, ini sebenarnya diangkat dalam versi berikutnya ke 8MBatau 16MB... tapi saya pikir untuk menempatkan ini ke dalam perspektif, Eliot dari 10gen (yang mengembangkan MongoDB) mengatakan yang terbaik:

EDIT: Ukuran telah resmi 'dinaikkan' menjadi16MB

Jadi, pada contoh blog Anda, 4MB sebenarnya sangat banyak .. Misalnya, teks lengkap tanpa kompres "War of the Worlds" hanya 364k (html): http://www.gutenberg.org/etext/36

Jika posting blog Anda selama itu dengan banyak komentar, saya tidak akan membacanya :)

Untuk trackback, jika Anda mendedikasikan 1MB untuknya, Anda dapat dengan mudah memiliki lebih dari 10rb (mungkin lebih dekat dengan 20rb)

Jadi kecuali untuk situasi yang benar-benar aneh, itu akan bekerja dengan baik. Dan dalam kasus pengecualian atau spam, saya benar-benar tidak berpikir Anda menginginkan objek 20MB. Saya pikir membatasi trackback sebagai 15k atau lebih masuk akal tidak peduli apa untuk kinerja. Atau setidaknya casing khusus jika pernah terjadi.

-Eliot

Saya pikir Anda akan sangat sulit ditekan untuk mencapai batas ... dan seiring waktu, jika Anda meningkatkan ... Anda harus semakin khawatir.

Poin utama dari batas ini adalah agar Anda tidak menggunakan semua RAM di server Anda (karena Anda perlu memuat semua MBdokumen ke dalam RAM ketika Anda menanyakannya.)

Jadi batasannya adalah beberapa% dari RAM normal yang dapat digunakan pada sistem umum ... yang akan terus tumbuh dari tahun ke tahun.

Catatan tentang Menyimpan File di MongoDB

Jika Anda perlu menyimpan dokumen (atau file) yang lebih besar daripada 16MBAnda dapat menggunakan API GridFS yang secara otomatis akan memecah data menjadi segmen-segmen dan mengalirkannya kembali ke Anda (sehingga menghindari masalah dengan batas ukuran / RAM.)

Alih-alih menyimpan file dalam satu dokumen, GridFS membagi file menjadi beberapa bagian, atau potongan, dan menyimpan setiap potongan sebagai dokumen terpisah.

GridFS menggunakan dua koleksi untuk menyimpan file. Satu koleksi menyimpan potongan file, dan lainnya menyimpan file metadata.

Anda dapat menggunakan metode ini untuk menyimpan gambar, file, video, dll dalam database sebanyak mungkin dalam database SQL. Saya telah menggunakan ini bahkan untuk menyimpan file video multi-gigabyte.


2
Itu luar biasa Anda memiliki RAM yang cukup untuk seluruh database Anda ... Biasanya "set kerja" dalam RAM, bukan seluruh database (seperti dalam kasus saya, saya memiliki lebih dari satu basis data x GB di mana jika semua ditambahkan akan melebihi RAM saya, tapi tidak apa-apa karena set kerjanya jauh, jauh lebih kecil.) Juga, jika tidak ada batasan Anda mungkin memuat dokumen 800MB ke dalam RAM dengan satu permintaan dan dokumen 400k dengan yang lain, membuat menyeimbangkan RAM Anda sedikit sulit, dan lain-lain Jadi "batasnya" adalah beberapa% dari RAM server tipikal (dengan demikian ia tumbuh seiring waktu.) Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins

3
Sangat bagus bahwa Anda dapat menyimpan semuanya dalam RAM, tetapi pertimbangkan efisiensi dan idiom posting blog. Anda jelas ingin posting berada di memori jika dibaca. Tetapi apakah Anda benar-benar ingin 10 halaman komentar untuk posting blog berada di memori ketika kebanyakan orang tidak akan pernah membaca melewati halaman pertama? Tentu, Anda bisa melakukannya dan jika basis data Anda cukup kecil sehingga semuanya bisa muat di memori, maka tidak ada masalah. Tetapi dalam hal efisiensi murni, Anda tidak ingin bit yang tidak berguna mengambil ruang memori jika Anda dapat menghindarinya (dan itu berlaku untuk RDBMS juga).
AlexGad

50
Ya Tuhan, jadi argumen Mongo adalah "16 MB sudah cukup untuk siapa pun"? Bukan seperti itu yang pernah terbukti salah di masa lalu.
Robert Christ

2
Ini sepertinya terlalu buruk bagi saya. Mongo seharusnya berguna untuk data besar, tidak memiliki batasan seperti itu. Dalam proyek saya, saya perlu mengumpulkan dan mengelompokkan tweet yang terkait dengan topik tren yang sama, dan ini mungkin berakhir di lebih dari 20.000 tweet untuk jangka waktu 20 jam (dan sangat mungkin bahwa akan ada tren selama lebih dari 20 jam di db saya). Memiliki banyak tweet dan menyimpan teks pada saat yang sama sangat menghancurkan dan setelah mengelompokkan beberapa tren kecil, berakhir dengan pengecualian pada tren besar.
Savvas Parastatidis

7
@savvas mengapa Anda menempatkan semua tweet dalam satu dokumen? Gunakan satu dokumen per tweet, letakkan topik trending sebagai bidang lain pada dokumen. menempatkan indeks pada bidang topik itu dan kemudian agregat pada bidang itu menggunakan pipa mongo. perlu beberapa penyesuaian tentang bagaimana Anda melakukan sesuatu untuk bekerja dengan nosql, setelah Anda menyesuaikan metode Anda dan berpikir Anda akan menemukan itu berfungsi dengan baik untuk banyak kasus penggunaan data besar.
schmidlop

32

Banyak orang di komunitas lebih suka tanpa batas dengan peringatan tentang kinerja, lihat komentar ini untuk argumen yang beralasan: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: comment-tabpanel # comment-22283

Saya kira, pengembang utama keras kepala tentang masalah ini karena mereka memutuskan itu adalah "fitur" penting sejak awal. Mereka tidak akan mengubahnya dalam waktu dekat karena perasaan mereka terluka bahwa ada yang mempertanyakannya. Contoh lain dari kepribadian dan politik yang mengurangi produk dalam komunitas open source tetapi ini bukan masalah yang melumpuhkan.


5
Saya setuju sepenuhnya dengan Anda, juga mengalahkan tujuan memiliki dokumen yang disematkan sekarang, karena sebagian besar dokumen yang disematkan sekarang akan melewati batas dengan mudah. Esp dengan berbagai dokumen di dalamnya
Sharjeel Ahmed

@ marr75 dikatakan sudah diperbaiki sekarang, apakah sudah diperbaiki?
Mafii

1
Maksud saya, batas dinaikkan menjadi 16MB, itu tidak memperbaiki "masalah" jangka panjang; IMO batasnya harus dihilangkan.
marr75

2
Necro utas berusia 6 tahun. Saya benar-benar tidak yakin dengan contoh kasus / desain buruk yang digunakan. Juga, contoh itu jauh lebih baik dalam menggambarkan mengapa Anda perlu memvalidasi input daripada memiliki batas ukuran dokumen tunggal database. Membuat aplikasi membagi dokumen bersarangnya sebagai dokumen individual dalam koleksi lain atau memulai dokumen "lanjutan" baru (solusi yang saya gunakan beberapa kali untuk bekerja dalam batas ini) berdampak kecil pada kinerja tetapi berdampak besar pada kompleksitas kode. Seluruh poin DB dokumen adalah lokalitas data.
marr75

4
Terima kasih telah melakukan soal matematika yang sama dengan dokumen mongoDB lakukan untuk mempertahankan keputusan ini, tetapi percobaan penggunaan tunggal dan pemikiran Anda jauh dari meyakinkan. Saya harus datang dengan desain yang rumit dan berlebihan untuk mengatasi kenyataan bahwa ada batas sewenang-wenang yang terkena mongo (tanpa entri yang bersarang atau digandakan, btw). Menurut logika Anda, tidak ada basis data yang harus mengandung total lebih dari 16MB karena beberapa teks arbitrer dapat direpresentasikan menggunakan penyimpanan yang lebih sedikit. Ini jelas konyol.
marr75

31

Untuk memposting jawaban klarifikasi di sini untuk mereka yang diarahkan di sini oleh Google.

Ukuran dokumen mencakup semua yang ada di dokumen termasuk sub dokumen, objek bersarang, dll.

Jadi dokumen dari:

{
    _id:{},
    na: [1,2,3],
    naa: [
        {w:1,v:2,b:[1,2,3]},
        {w:5,b:2,h:[{d:5,g:7},{}]}
    ]
}

Memiliki ukuran maksimum 16meg.

Dokumen-dokumen dan benda-benda bersarang dihitung berdasarkan ukuran dokumen.


Struktur tunggal terbesar yang mungkin dapat direpresentasikan dalam BSON adalah, ironisnya, juga yang paling kompak. Terlepas dari kenyataan bahwa MongoDB menggunakan size_tindeks array (64-bit) secara internal, batas ukuran dokumen 16MB akan, paling-paling, dapat mewakili dokumen yang mengandung satu array itu sendiri yang mengandung dua juta NULL.
amcgregor

Permintaan maaf, menambahkan komentar kedua untuk mengatasi / mengklarifikasi detail penting lainnya: ketika Anda mengatakan ukuran dokumen mencakup semua yang ada dalam dokumen , itu juga termasuk kunci . Misal {"f": 1}dua byte lebih kecil dari {"foo": 1}. Ini dapat bertambah dengan cepat jika Anda tidak berhati-hati, meskipun kompresi pada disk modern memang membantu.
amcgregor

6

Saya belum melihat masalah dengan batas yang tidak melibatkan file besar yang tersimpan dalam dokumen itu sendiri. Sudah ada berbagai database yang sangat efisien dalam menyimpan / mengambil file besar; mereka disebut sistem operasi. Basis data ada sebagai lapisan di atas sistem operasi. Jika Anda menggunakan solusi NoSQL untuk alasan kinerja, mengapa Anda ingin menambahkan overhead pemrosesan tambahan untuk akses data Anda dengan meletakkan lapisan DB antara aplikasi Anda dan data Anda?

JSON adalah format teks. Jadi, jika Anda mengakses data Anda melalui JSON, ini terutama benar jika Anda memiliki file biner karena harus dikodekan dalam uuencode, heksadesimal, atau Basis 64. Jalur konversi mungkin terlihat seperti

file biner <> JSON (disandikan) <> BSON (disandikan)

Akan lebih efisien untuk meletakkan path (URL) ke file data dalam dokumen Anda dan menyimpan data itu sendiri dalam biner.

Jika Anda benar-benar ingin menyimpan file-file ini dengan panjang yang tidak diketahui dalam DB Anda, maka Anda mungkin akan lebih baik meletakkannya di GridFS dan tidak berisiko membunuh konkurensi Anda ketika file besar diakses.


1
"Sudah ada berbagai database yang sangat efisien dalam menyimpan / mengambil file besar; mereka disebut sistem operasi."; Lihat blog.mongodb.org/post/183689081/…
redcalx


2

Mungkin menyimpan posting blog -> hubungan komentar dalam database non-relasional sebenarnya bukan desain terbaik.

Anda mungkin harus menyimpan komentar dalam koleksi terpisah untuk posting blog.

[sunting]

Lihat komentar di bawah untuk diskusi lebih lanjut.


15
Saya tidak setuju sama sekali. Komentar dalam dokumen pos blog Anda harus benar-benar baik-baik saja di MongoDB ... ini adalah penggunaan yang sangat umum (saya menggunakannya lebih dari satu tempat dalam produksi dan berfungsi dengan baik.)
Justin Jenkins

2
Mungkin jawaban saya terlalu ketat. Tidak ada yang salah dalam menyimpan posting blog dan komentar terkait di MongoDB atau database serupa. Lebih banyak orang cenderung terlalu sering menggunakan kemampuan yang diberikan oleh basis data dokumen (contoh paling radikal adalah menyimpan semua data Anda dalam satu dokumen yang disebut 'blog')
Mchl

3
@Mchel: "blog" tidak bagus, tetapi menyimpan komentar dalam koleksi terpisah sama buruknya dengan alasan yang sama. Posting dengan larik komentar seperti, contoh kanonis dokumen db.
Matt Briggs

6
@SoPeople: menyimpan komentar di dalam sebuah tulisan seperti contoh kanonik dari DB yang berorientasi pada Dokumen. (Seperti menyimpan keseluruhan teks wiki di dalam satu dokumen) Jika saya menulis SO, itu akan berjalan sepenuhnya pada MongoDB. Tak satu pun dari entri SO ini akan cukup melebihi 4MB. Craigslist melakukan migrasi DB raksasa dari sejarah mereka ke MongoDB. Mereka hanya meminta beberapa dokumen melewati batas itu dan pengembang utama menyarankan agar dokumen itu sendiri benar-benar rusak (hasil dari beberapa bug). Sekali lagi, 4 MB adalah beberapa novel teks.
Gates VP

3
@ Gerbang VP, saya setuju untuk menggunakan mesin teks lengkap yang terpisah. Saya sedang memikirkan pencarian metadata. Bagaimana jika Anda memiliki satu set dokumen Buku, dan Anda ingin menemukan semua buku yang diterbitkan pada tahun 1982? Jika setiap buku memiliki + 100kb teks, Anda tidak ingin mentransfer beberapa megabyte hanya untuk menampilkan 20 judul buku pertama.
mikerobi

0

Menurut https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1

Jika Anda berharap bahwa posting blog dapat melebihi batas dokumen 16Mb, Anda harus mengekstraksi komentar ke dalam koleksi terpisah dan merujuk posting blog dari komentar dan melakukan penggabungan tingkat aplikasi.

// posts
[
  {
    _id: ObjectID('AAAA'),
    text: 'a post',
    ...
  }
]

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.