MongoDB BSON Belge boyutu sınırını anlama


153

MongoDB'den Kesin Kılavuz:

4 MB'tan büyük belgeler (BSON'a dönüştürüldüğünde) veritabanına kaydedilemez. Bu biraz keyfi bir sınırdır (ve gelecekte de arttırılabilir); çoğunlukla kötü şema tasarımını önlemek ve tutarlı performans sağlamaktır.

Bu sınırı anlamıyorum, bu, 4 MB'den daha büyük olan çok sayıda yorum içeren bir Blog yayını içeren bir Dokümanın tek bir doküman olarak saklanamayacağı anlamına mı geliyor?

Ayrıca bu iç içe geçmiş belgeleri de sayar mı?

Bir değerdeki değişiklikleri denetleyen bir belge istesem ne olur? (Sonunda 4 MB sınırını aşarak büyüyebilir.)

Umarım birisi bunu doğru bir şekilde açıklar.

Sadece MongoDB (ilk öğrendiğim nosql veritabanı) hakkında okumaya başladım.

Teşekkür ederim.


5
Sorunun bunun MongoDB saklanan belge boyutlarının BSON formatında değil, bir sınırlama olduğunu açıklığa kavuşturması gerektiğini düşünüyorum.
alexpopescu

2
Yine de, "BSON :: InvalidDocument: Belge çok büyük: BSON belgeleri 4194304 bayt ile sınırlıdır." Bu durumda, uyarı / hata mesajında ​​bir tür yanıltıcı değil mi?
Nik So

18
Maksimum BSON belge boyutunuzu kabuktaki db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'komutla kolayca bulabilirsiniz mongo.
AhmetB - Google

5
16 mb'den fazla kayıt dökümü ve üstüne crud operasyon inşa edemez şematik nosql amacı nedir!
Rizwan Patel

Sanırım ilk alıntı her şeyi söylüyor ... Kötü şema tasarımını önlemek için sınır var. Örneğin, çok sayıda yorumu olan bir yayınınız varsa, bir blog girişi koleksiyonu ve bir yorum koleksiyonu veya bir değişiklik koleksiyonu istersiniz. Mongo / nosql tasarımı, belge ağları olarak büyük boyutlu şeylere izin verir, ancak geliştiricinin bunları anlamlı olan parçalara ayırması gerekir. Boyut sınırı ayarlanmazsa, başka sorunlar ortaya çıkar. 4mb sınırı iyi olduğunu düşünüyorum. 16mb, harika! Ancak 16mb'lik bir belge yazıyorsam, tasarımda başka bir şeyin yanlış olduğuna dair bir ipucu.
Kirpik

Yanıtlar:


126

Öncelikle, bu aslında bir sonraki versiyonda yükseltiliyor 8MBveya 16MB... ama bunu perspektif haline getirmeyi düşünüyorum, 10gen'den (MongoDB'yi geliştiren) Eliot bunu en iyi şekilde ortaya koyuyor:

EDIT: Boyut resmi olarak 'yükseltildi'16MB

Yani, blog örneğinizde, 4MB aslında çok fazla .. Örneğin, "World of Wars" ın tam sıkıştırılmamış metni sadece 364k (html): http://www.gutenberg.org/etext/36

Blog yazınız bu kadar çok yorumla o kadar uzunsa, bir tanesi için ben okumam :)

Geri izleme için, onlara 1 MB ayırdıysanız, kolayca 10k'den fazla olabilirsiniz (muhtemelen 20k'ye daha yakın)

Bu yüzden gerçekten tuhaf durumlar dışında, harika çalışır. İstisna durumunda veya spam durumunda, yine de 20mb'lik bir nesne isteyeceğinizi düşünmüyorum. Ben geri izleme 15k ya da öylesine kapak performans için ne olursa olsun çok mantıklı düşünüyorum. Ya da en azından özel bir kasa olursa.

-Eliot

Sanırım sınıra ulaşmak için oldukça zorlanacaksınız ... ve zamanla, yükseltme yaparsanız ... daha az endişelenmeniz gerekecek.

Limitin ana noktası, sunucunuzdaki tüm RAM'leri kullanmamanızdır ( MBsorgularken belgenin tüm s'lerini RAM'e yüklemeniz gerekir.)

Bu nedenle sınır, ortak bir sistemdeki normal kullanılabilir RAM'in% bir kısmı ... bu da her geçen yıl büyümeye devam edecek.

MongoDB'de Dosya Saklama Hakkında Not

Belgeleri (veya dosyaları) depolamanız gerekiyorsa , verileri otomatik olarak bölümlere ayıracak ve size geri aktaracak GridFS API'sını16MB kullanabilirsiniz (böylece boyut sınırları / RAM ile ilgili sorunu önler).

Bir dosyayı tek bir belgede saklamak yerine, GridFS dosyayı parçalara veya parçalara böler ve her bir parçayı ayrı bir belge olarak saklar.

GridFS dosyaları depolamak için iki koleksiyon kullanır. Bir koleksiyon dosya yığınlarını, diğeri dosya meta verilerini depolar.

Bu yöntemi, görüntüleri, dosyaları, videoları vb. Bir SQL veritabanında olabildiğince veritabanında depolamak için kullanabilirsiniz. Bunu çok gigabayt video dosyalarını bile saklamak için kullandım.


2
Tüm veritabanınız için yeterli RAM'e sahip olduğunuz müthiş ... Tipik olarak "çalışma kümesi" RAM'de, tüm veritabanında değil (benim durumumda, birden fazla x GBs veritabanım varsa, burada toplanan RAM'imin tamamını aşarsa, ancak bu tamam çünkü çalışma kümesi çok, çok daha küçük.) Ayrıca, herhangi bir sınır yoksa, bir RAM w / 800MB dokümanı ve diğeri ile 400k dokümanı yükleyebilir, RAM'inizi dengelemeyi biraz zorlaştırabilirsiniz, vb. "Sınır", tipik sunucu RAM'inin% 'si kadardır (bu nedenle zamanla büyür.) Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins

3
Her şeyi RAM'de saklayabilmeniz harika, ancak verimliliği ve blog yazısı deyimini düşünün. Açıkçası bir yayının okunması durumunda bellekte olmasını istersiniz. Ancak, bir blog yayınının çoğu insan ilk sayfayı hiç okumadığında hafızada kalmasını gerçekten istiyor musunuz? Tabii, bunu yapabilirsiniz ve veritabanınız hepsi belleğe sığacak kadar küçükse, o zaman sorun yok. Ancak saf verimlilik açısından, kaçınabiliyorsanız (ve RDBMS için de geçerlidir) işe yaramaz bitlerin bellek alanını kaplamasını istemezsiniz.
AlexGad

50
tatlı İsa, yani Mongo'nun argümanı "16 MB herkes için yeterli olmalı" dır? Bu böyle değil geçmişte yanlış olduğu kanıtlanmıştır.
Robert Christ

2
Bu benim için çok kötü görünüyor. Moğolun büyük veriler için yararlı olduğu varsayılır, bu tür sınırlamalar yoktur. Projemde, aynı trend konuyla ilgili tweet'leri toplamam ve gruplandırmam gerekiyor ve bu 20 saatlik bir süre boyunca 20000'den fazla tweet'e neden olabilir (ve daha uzun süren trendlerin olması oldukça olasıdır. Db'de 20 saat). Bu kadar çok tweet'e sahip olmak ve aynı anda metinlerini saklamak yıkıcıdır ve birkaç küçük eğilimi grupladıktan sonra, büyük bir eğilimde istisna ile sonuçlanır.
Savvas Parastatidis

7
@savvas tüm tweetleri neden tek bir belgeye koydun? Tweet başına bir belge kullanın, trend olan konuyu belgede başka bir alan olarak yerleştirin. o konu alanına bir indeks koyun ve daha sonra mongo boru hattını kullanarak o alanda toplayın. nosql ile çalışmak için işleri nasıl yapacağınız konusunda bazı ayarlamalar yapmak gerekir, yöntemlerinizi ayarladıktan ve birçok büyük veri kullanım durumu için harika çalışacağını düşündüğünüzde.
schmidlop

32

Topluluktaki birçoğu performansla ilgili uyarılarla sınır tanımayı tercih etmez, iyi gerekçeli bir argüman için bu yoruma bakın: https://jira.mongodb.org/browse/SERVER-431?focusedCommentId=22283&page=com.atlassian.jira.plugin. system.issuetabpanels: comment-TabPanel # comment-22283

Benim düşüncem, baş geliştiriciler bu konuda inatçı çünkü erken bir zamanda önemli bir "özellik" olduğuna karar verdiler. Yakında bunu değiştirmeyecekler, çünkü duyguları kimsenin sorguladığı için yaralandı. Açık kaynak topluluklarındaki bir üründen uzaklaşan kişilik ve siyasetin başka bir örneği ama bu gerçekten sakat bir mesele değil.


5
Size tamamen katılıyorum, aynı zamanda şimdi gömülü belgelere sahip olma amacını da yitiriyor, çünkü gömülü belgelerin çoğu artık sınırı kolayca geçecek. İçlerinde belge dizisi bulunan Esp
Sharjeel Ahmed

@ marr75 şu anda düzeltildi diyor, düzeltildi mi?
Mafii

1
Yani, sınır "MB" uzun vadede düzeltmek değil 16MB'a yükseltildi; IMO limiti ortadan kaldırılmalıdır.
marr75

2
6 yaşındaki iplik necro. Özel kötü kullanım durumunuza / tasarım örneğinize kesinlikle ikna olmadım. Ayrıca, bu örnek, veri tabanlarını tek bir veritabanı boyutu sınırına sahip olmak yerine girişleri neden doğrulamanız gerektiğini göstermede çok daha iyidir. Uygulamanın başka bir koleksiyondaki yuvalanmış belgelerini ayrı ayrı belgeler olarak ayırmasını veya yeni bir "devam" belgesini başlatmasını (bu sınırda çalışmak için birkaç kez kullandığım çözümler) performans üzerinde çok az etkisi olsa da kod karmaşıklığı üzerinde büyük etkileri oldu. Belge DB'lerinin tüm noktası veri yerelliğidir.
marr75

4
Aynı matematiği yaptığınız için teşekkürler mongoDB belgeleri bu kararı savunmak için yapar, ancak tek kullanımlık durumunuz ve düşünce denemeniz kesin olmaktan uzaktır. Ben (derin iç içe veya yinelenen girişler olmadan, btw) mongo tarafından vurulur keyfi bir sınır olduğu gerçeği geçici çözüm için karmaşık, gereksiz tasarımlar ile gelmek zorunda kaldı. Mantıklarınıza göre, hiçbir veritabanının toplamda 16 MB'tan fazla içermesi gerekmez, çünkü bazı keyfi metinler daha az depolama alanı kullanılarak temsil edilebilir. Bu açıkça saçma.
marr75

31

Burada Google tarafından yönlendirilenlere açıklayıcı bir yanıt göndermek için.

Belge boyutu, alt belgeler, iç içe nesneler vb. Dahil olmak üzere belgedeki her şeyi içerir.

Yani bir belge:

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

Maksimum 16meg boyuta sahiptir.

Sbudocuments ve iç içe nesnelerin tümü, belgenin boyutuna göre sayılır.


BSON'da temsil edilebilecek mümkün olan en büyük tek yapı, ironik olarak, aynı zamanda en kompakt olanıdır. MongoDB'nin size_tdahili olarak (64 bit) dizi indeksleri kullanmasına rağmen, 16MB belge boyutu sınırı en iyi ihtimalle iki milyon NULL içeren tek bir dizi içeren bir belgeyi temsil edebilir.
amcgregor

Özür dileriz, başka bir önemli ayrıntıya hitap etmek / netleştirmek için ikinci yorum ekliyoruz: belge boyutunun belgedeki her şeyi içerdiğini söylediğinizde , anahtarları da içerir . Örneğin {"f": 1}iki bayt daha küçüktür {"foo": 1}. Modern disk üstü sıkıştırma yardımcı olsa da, dikkatli değilseniz bu hızla toplanabilir.
amcgregor

6

Henüz belgenin içinde saklanan büyük dosyaları içermeyen sınırlama ile ilgili bir sorun görmedim. Büyük dosyaları depolamak / almakta çok verimli olan çeşitli veritabanları zaten vardır; bunlara işletim sistemleri denir. Veritabanı, işletim sistemi üzerinde bir katman olarak bulunur. Performans nedenleriyle bir NoSQL çözümü kullanıyorsanız, neden DB katmanını uygulamanız ve verileriniz arasına koyarak verilerinizin erişimine ek işlem yükü eklemek istesiniz ki?

JSON bir metin biçimidir. Dolayısıyla, verilerinize JSON üzerinden erişiyorsanız, ikili dosyalarınız varsa bu özellikle doğrudur, çünkü bunların uuencode, hexadecimal veya Base 64 olarak kodlanması gerekir.

ikili dosya <> JSON (kodlanmış) <> BSON (kodlanmış)

Belgenizdeki veri dosyasının yolunu (URL) koymak ve verileri ikili olarak tutmak daha verimli olur.

Bu uzunluğu bilinmeyen dosyaları gerçekten DB'nizde tutmak istiyorsanız, büyük olasılıkla büyük dosyalara erişildiğinde bunları GridFS'ye koymak ve eşzamanlılığınızı öldürme riskini almamak daha iyi olur.


1
"Büyük dosyaları depolamak / almakta çok verimli olan çeşitli veritabanları zaten var; bunlara işletim sistemi deniyor."; Bkz. Blog.mongodb.org/post/183689081/…
redcalx


2

Belki bir blog yazısı -> yorum ilişkisini ilişkisel olmayan bir veritabanında saklamak gerçekten en iyi tasarım değildir.

Yine de blog yayınları için yorumları ayrı bir koleksiyonda saklamanız gerekir.

[Düzenle]

Daha fazla tartışma için aşağıdaki yorumlara bakın.


15
Hiç katılmıyorum. Blog yazı belgelerinizdeki yorumlar MongoDB'de mükemmel olmalı ... çok yaygın bir kullanım (üretimde birden fazla yer kullanıyorum ve oldukça iyi çalışıyor.)
Justin Jenkins

2
Cevabımda belki de çok katı davrandım. Blog gönderilerini ve ilişkili yorumları MongoDB veya benzeri bir veritabanında depolamakta yanlış bir şey yoktur. İnsanların belge tabanlı veritabanlarının verdiği yetenekleri aşırı kullanma eğilimi daha fazladır (en radikal örnek, tüm verilerinizi 'blog' adlı tek bir belgede saklamak olacaktır)
Mchl

3
@Mchel: "blog" iyi değil, ancak yorumları ayrı bir koleksiyonda saklamak aynı nedenlerden dolayı kötü. Bir yorum dizisi olan gönderiler, bir belge db'nin topçu örneği gibidir.
Matt Briggs

6
@SoPeople: bir gönderi içinde yorum depolamak Belge Odaklı DB'lerin standart örneği gibidir. (bir wiki metninin tamamını bir belgenin içinde saklamak gibi) SO yazacak olsaydım, tamamen MongoDB'de çalışacaktı. Bu SO girişlerinin hiçbiri gidiyor makul 4MB aşar. Craigslist, tarihlerinin MongoDB'ye devasa bir DB göçü gerçekleştiriyor. Sadece birkaç dokümanı bu sınırı aştılar ve baş geliştirici, dokümanların kendilerinin gerçekten yakalandığını (bazı hataların sonucu) önerdi. Yine 4 meg metin birkaç romanıdır.
Gates VP

3
@ Gates VP, ayrı bir tam metin motoru kullanmayı kabul ediyorum. Bir meta veri araması düşünüyordum. Bir dizi Kitap belgeniz varsa ve 1982'de yayınlanan tüm kitapları bulmak istiyorsanız ne olur? Her kitabın + 100 kb'lik metni varsa, yalnızca ilk 20 kitap başlığını görüntülemek için birkaç megabayt aktarmak istemezsiniz.
mikerobi

0

Https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1'e göre

Bir blog gönderisinin 16 MB belge sınırını aşabileceğini düşünüyorsanız, yorumları ayrı bir koleksiyona çıkarmalı ve yorumdan blog gönderisine başvurmalı ve uygulama düzeyinde bir katılma yapmalısınız.

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

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.