Hiểu giới hạn kích thước tài liệu MongoDB BSON


153

Từ MongoDB Hướng dẫn dứt khoát:

Tài liệu lớn hơn 4MB (khi được chuyển đổi thành BSON) không thể được lưu vào cơ sở dữ liệu. Đây là một giới hạn tùy ý (và có thể được nêu ra trong tương lai); nó chủ yếu là để ngăn chặn thiết kế lược đồ xấu và đảm bảo hiệu suất phù hợp.

Tôi không hiểu giới hạn này, điều này có nghĩa là Tài liệu có chứa một bài đăng trên Blog có rất nhiều bình luận chỉ lớn hơn 4 MB không thể được lưu trữ dưới dạng một tài liệu?

Điều này cũng tính các tài liệu lồng nhau quá?

Điều gì xảy ra nếu tôi muốn một tài liệu kiểm tra các thay đổi thành giá trị. (Cuối cùng nó sẽ có thể phát triển, vượt quá giới hạn 4 MB.)

Hy vọng ai đó giải thích điều này một cách chính xác.

Tôi mới bắt đầu đọc về MongoDB (cơ sở dữ liệu nosql đầu tiên tôi đang tìm hiểu).

Cảm ơn bạn.


5
Tôi nghĩ rằng câu hỏi nên làm rõ rằng đây là một giới hạn về kích thước tài liệu được lưu trữ MongoDB chứ không phải định dạng BSON.
alexpopescu

2
Mặc dù vậy, tôi vừa thử lưu một tài liệu khổng lồ chắc chắn vượt quá 4 MB để nhận được thông báo "BSON :: UnlimitedDocument: Tài liệu quá lớn: Tài liệu BSON bị giới hạn ở mức 4194304 byte." Nếu đó là trường hợp, nó không phải là loại gây hiểu lầm trong thông báo cảnh báo / lỗi?
Nik So

18
Bạn có thể dễ dàng tìm thấy kích thước tài liệu BSON tối đa của mình bằng db.isMaster().maxBsonObjectSize/(1024*1024)+' MB'lệnh in mongoshell.
AhmetB - Google

5
Mục đích của schemaless nosql là gì khi bạn không thể kết xuất các bản ghi lớn hơn 16 mb và xây dựng hoạt động thô sơ trên nó!
Rizwan Patel

Tôi nghĩ rằng trích dẫn ban đầu nói lên tất cả ... Giới hạn được đặt ra để ngăn chặn thiết kế lược đồ xấu. Ví dụ, nếu bạn có một bài đăng có nhiều bình luận, bạn sẽ muốn có một bộ sưu tập mục blog và một bộ sưu tập bình luận, hoặc một bộ sưu tập thay đổi. Thiết kế của mongo / nosql cho phép những thứ có kích thước ồ ạt như các mạng tài liệu, nhưng nhà phát triển cần chia chúng thành các phần có ý nghĩa. Nếu không có giới hạn kích thước được đặt, các vấn đề khác sẽ xảy ra. Tôi nghĩ rằng giới hạn 4mb là tốt. 16mb, thật tuyệt! Nhưng nếu tôi đang viết một tài liệu 16mb, thì đó là manh mối cho thấy có gì đó không ổn với thiết kế.
Lông mi

Câu trả lời:


126

Trước hết, điều này thực sự đang được nâng lên trong phiên bản tiếp theo 8MBhoặc 16MB... nhưng tôi nghĩ để đưa điều này vào viễn cảnh, Eliot từ 10gen (người đã phát triển MongoDB) đưa nó tốt nhất:

EDIT: Kích thước đã chính thức được 'nâng' lên16MB

Vì vậy, trên ví dụ blog của bạn, 4MB thực sự là rất nhiều .. Ví dụ: toàn bộ văn bản giải nén của "Chiến tranh thế giới" chỉ có 364k (html): http://www.gutenberg.org/etext/36

Nếu bài đăng trên blog của bạn dài như vậy với nhiều bình luận, tôi sẽ không đọc nó :)

Đối với trackback, nếu bạn dành riêng 1MB cho chúng, bạn có thể dễ dàng có hơn 10k (có thể gần hơn 20k)

Vì vậy, ngoại trừ những tình huống thực sự kỳ lạ, nó sẽ hoạt động rất tốt. Và trong trường hợp ngoại lệ hoặc spam, tôi thực sự không nghĩ rằng bạn muốn có một đối tượng 20mb. Tôi nghĩ giới hạn theo dõi là 15k hoặc hơn rất nhiều ý nghĩa cho dù hiệu suất. Hoặc ít nhất là vỏ đặc biệt nếu nó từng xảy ra.

-Eliot

Tôi nghĩ rằng bạn sẽ khá khó khăn để đạt đến giới hạn ... và theo thời gian, nếu bạn nâng cấp ... bạn sẽ phải lo lắng ngày càng ít đi.

Điểm chính của giới hạn là vì vậy bạn không sử dụng hết RAM trên máy chủ của mình (vì bạn cần tải tất cả MBs của tài liệu vào RAM khi bạn truy vấn nó.)

Vì vậy, giới hạn là một số% RAM có thể sử dụng bình thường trên một hệ thống chung ... sẽ tiếp tục tăng lên hàng năm.

Lưu ý về việc lưu trữ tệp trong MongoDB

Nếu bạn cần lưu trữ tài liệu (hoặc tệp) lớn hơn 16MBbạn có thể sử dụng API GridFS , nó sẽ tự động chia dữ liệu thành các phân đoạn và truyền chúng lại cho bạn (do đó tránh được vấn đề về giới hạn kích thước / RAM.)

Thay vì lưu trữ một tệp trong một tài liệu, GridFS chia tệp thành các phần hoặc khối và lưu trữ từng đoạn dưới dạng một tài liệu riêng biệt.

GridFS sử dụng hai bộ sưu tập để lưu trữ các tập tin. Một bộ sưu tập lưu trữ các khối tệp và bộ lưu trữ siêu dữ liệu khác.

Bạn có thể sử dụng phương pháp này để lưu trữ hình ảnh, tệp, video, v.v. trong cơ sở dữ liệu nhiều như bạn có thể trong cơ sở dữ liệu SQL. Tôi đã sử dụng điều này để thậm chí lưu trữ các tập tin video nhiều gigabyte.


2
Thật tuyệt vời khi bạn có đủ RAM cho toàn bộ cơ sở dữ liệu của mình ... Thông thường, "bộ làm việc" nằm trong RAM, không phải toàn bộ cơ sở dữ liệu (như trong trường hợp của tôi, tôi có nhiều hơn một cơ sở dữ liệu x GB trong đó nếu tất cả được bổ sung sẽ vượt quá RAM của tôi, nhưng không sao vì bộ công việc nhỏ hơn nhiều.) Ngoài ra, nếu không có giới hạn, bạn có thể tải tài liệu 800 MB vào RAM với một truy vấn và tài liệu 400k với một truy vấn khác, khiến việc cân bằng RAM của bạn hơi khó khăn, v.v. Vì vậy, "giới hạn" là một số% RAM máy chủ thông thường (do đó nó tăng theo thời gian.) Mongodb.org/display/DOCS/Checking+Server+Memory+Usage
Justin Jenkins

3
Thật tuyệt khi bạn có thể lưu trữ mọi thứ trong RAM, nhưng hãy xem xét hiệu quả và thành ngữ bài đăng trên blog. Bạn rõ ràng muốn một bài viết trong bộ nhớ nếu nó đọc. Nhưng bạn có thực sự muốn 10 trang bình luận cho một bài đăng trên blog trong bộ nhớ khi hầu hết mọi người sẽ không bao giờ đọc qua trang đầu tiên? Chắc chắn, bạn có thể làm điều đó và nếu cơ sở dữ liệu của bạn đủ nhỏ để tất cả có thể phù hợp với bộ nhớ, thì không vấn đề gì. Nhưng về mặt hiệu quả thuần túy, bạn không muốn các bit vô dụng chiếm dung lượng bộ nhớ nếu bạn có thể tránh nó (và điều đó cũng đúng với RDBMS).
AlexGad

50
jesus ngọt ngào, vậy lập luận của Mongo là "16 MB là đủ cho bất cứ ai"? Nó không giống như điều đó đã từng được chứng minh là không chính xác trong quá khứ.
Robert Christ

2
Điều này có vẻ quá tệ cho tôi. Mongo được cho là hữu ích cho dữ liệu lớn, không có những hạn chế như vậy. Trong dự án của tôi, tôi cần tổng hợp và nhóm các tweet có liên quan đến cùng một chủ đề xu hướng và điều này có thể kết thúc trong hơn 20000 tweet trong khoảng thời gian 20 giờ (và hoàn toàn có khả năng sẽ có xu hướng kéo dài hơn 20 giờ trong db của tôi). Có nhiều tweet và lưu trữ văn bản của họ cùng một lúc là tàn phá và sau khi nhóm một vài xu hướng nhỏ, nó kết thúc ngoại lệ trên một xu hướng lớn.
Savvas Parastatidis

7
@savvas tại sao bạn sẽ đặt tất cả các tweet trong tài liệu duy nhất? Sử dụng một tài liệu trên mỗi tweet, đặt chủ đề xu hướng là một trường khác trên tài liệu. đặt một chỉ mục trên trường chủ đề đó và sau đó tổng hợp trên trường đó bằng cách sử dụng đường ống mongo. cần có một số điều chỉnh về cách bạn làm mọi thứ để làm việc với nosql, một khi bạn điều chỉnh các phương thức của mình và nghĩ rằng bạn sẽ thấy nó hoạt động tốt cho nhiều trường hợp sử dụng dữ liệu lớn.
schmidlop

32

Nhiều người trong cộng đồng không muốn có giới hạn với các cảnh báo về hiệu suất, hãy xem nhận xét này để biết lý lẽ hợp lý: https://jira.mongodb.org/browse/SERVER-431?f FocusedVerId = 22283 & page = com.atlassian.jira.plugin . system.issuetabpanels: bình luận-tabpanel # bình luận-22283

Tôi nghĩ, các nhà phát triển chính rất bướng bỉnh về vấn đề này bởi vì họ đã quyết định rằng đây là một "tính năng" quan trọng từ rất sớm. Họ sẽ không thay đổi nó bất cứ lúc nào sớm vì cảm xúc của họ bị tổn thương mà bất cứ ai cũng nghi ngờ điều đó. Một ví dụ khác về tính cách và chính trị làm mất tập trung từ một sản phẩm trong các cộng đồng nguồn mở nhưng đây không thực sự là một vấn đề tê liệt.


5
Tôi hoàn toàn đồng ý với bạn, nó cũng đánh bại mục đích có các tài liệu nhúng ngay bây giờ, vì hầu hết các tài liệu nhúng bây giờ sẽ vượt qua giới hạn một cách dễ dàng. Esp với một loạt các tài liệu bên trong chúng
Sharjeel Ahmed

@ marr75 nó nói đã sửa rồi, đã sửa chưa?
Mafii

1
Ý tôi là, giới hạn đã được nâng lên 16 MB, điều đó không khắc phục được "vấn đề" lâu dài; IMO giới hạn nên được loại bỏ.
marr75

2
Necro 6 tuổi. Tôi chắc chắn không bị thuyết phục bởi ví dụ thiết kế / trường hợp sử dụng xấu cụ thể của bạn. Ngoài ra, ví dụ đó tốt hơn nhiều trong việc minh họa lý do tại sao bạn cần xác thực các đầu vào hơn là có giới hạn kích thước tài liệu duy nhất của cơ sở dữ liệu. Làm cho ứng dụng tách các tài liệu lồng nhau của nó thành các tài liệu riêng lẻ trong một bộ sưu tập khác hoặc bắt đầu một tài liệu "tiếp tục" mới (các giải pháp tôi đã sử dụng nhiều lần để làm việc trong giới hạn này) ít ảnh hưởng đến hiệu suất nhưng tác động lớn đến độ phức tạp của mã. Toàn bộ điểm của DB tài liệu là địa phương dữ liệu.
marr75

4
Cảm ơn bạn đã thực hiện cùng một phép toán mà các tài liệu mongoDB thực hiện để bảo vệ quyết định này, nhưng trường hợp sử dụng duy nhất và thử nghiệm suy nghĩ của bạn không thể kết luận được. Tôi đã phải đưa ra các thiết kế phức tạp, dư thừa để khắc phục sự thật rằng có một giới hạn tùy ý bị tấn công bởi mongo (không có các mục được lồng hoặc trùng lặp sâu, btw). Theo logic của bạn, không có cơ sở dữ liệu nào cần chứa tổng cộng hơn 16 MB vì ​​một số văn bản tùy ý có thể được biểu diễn bằng cách sử dụng ít bộ nhớ hơn. Điều này rõ ràng là ngớ ngẩn.
marr75

31

Để đăng câu trả lời làm rõ ở đây cho những người được Google hướng dẫn ở đây.

Kích thước tài liệu bao gồm mọi thứ trong tài liệu bao gồm các bản đồ con, các đối tượng lồng nhau, v.v.

Vì vậy, một tài liệu về:

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

Có kích thước tối đa 16meg.

Sbudocument và các đối tượng lồng nhau đều được tính vào kích thước của tài liệu.


Cấu trúc lớn nhất có thể có thể được trình bày trong BSON, trớ trêu thay, cũng nhỏ gọn nhất. Mặc dù thực tế MongoDB sử dụng size_tcác chỉ mục mảng (64 bit) bên trong, nhưng giới hạn kích thước tài liệu 16 MB, tốt nhất có thể đại diện cho một tài liệu chứa một mảng duy nhất chứa hai triệu NULL.
amcgregor 26/03/19

Xin lỗi, thêm nhận xét thứ hai để giải quyết / làm rõ một chi tiết quan trọng khác: khi bạn nói kích thước tài liệu bao gồm mọi thứ trong tài liệu , cũng bao gồm các khóa . Ví dụ: {"f": 1}hai byte nhỏ hơn {"foo": 1}. Điều này có thể nhanh chóng bổ sung nếu bạn không cẩn thận, mặc dù nén trên đĩa hiện đại có ích.
amcgregor 26/03/19

6

Tôi chưa thấy vấn đề với giới hạn không liên quan đến các tệp lớn được lưu trữ trong chính tài liệu. Hiện đã có một loạt các cơ sở dữ liệu rất hiệu quả trong việc lưu trữ / truy xuất các tệp lớn; chúng được gọi là hệ điều hành. Cơ sở dữ liệu tồn tại dưới dạng một lớp trên hệ điều hành. Nếu bạn đang sử dụng giải pháp NoQuery vì lý do hiệu năng, tại sao bạn muốn thêm chi phí xử lý bổ sung vào quyền truy cập dữ liệu của mình bằng cách đặt lớp DB giữa ứng dụng và dữ liệu của bạn?

JSON là một định dạng văn bản. Vì vậy, nếu bạn đang truy cập dữ liệu của mình thông qua JSON, điều này đặc biệt đúng nếu bạn có tệp nhị phân vì chúng phải được mã hóa theo uuencode, hexadecimal hoặc Base 64. Đường dẫn chuyển đổi có thể trông giống như

tệp nhị phân <> JSON (được mã hóa) <> BSON (được mã hóa)

Sẽ hiệu quả hơn nếu đặt đường dẫn (URL) vào tệp dữ liệu trong tài liệu của bạn và giữ dữ liệu ở dạng nhị phân.

Nếu bạn thực sự muốn giữ các tệp này có độ dài không xác định trong DB của mình, thì có lẽ tốt hơn hết bạn nên đặt chúng trong GridFS và không mạo hiểm giết chết đồng thời của bạn khi các tệp lớn được truy cập.


1
"Đã có một loạt các cơ sở dữ liệu rất hiệu quả trong việc lưu trữ / truy xuất các tệp lớn; chúng được gọi là hệ điều hành."; Xem blog.mongodb.org/post/183689081/ Ấn
redcalx 13/07/2015


2

Có lẽ lưu trữ một bài đăng blog -> quan hệ bình luận trong cơ sở dữ liệu không liên quan không thực sự là thiết kế tốt nhất.

Bạn có lẽ nên lưu trữ ý kiến ​​trong một bộ sưu tập riêng biệt cho các bài đăng blog.

[biên tập]

Xem ý kiến ​​dưới đây để thảo luận thêm.


15
Tôi không đồng ý chút nào. Nhận xét trong tài liệu bài đăng trên blog của bạn sẽ hoàn toàn ổn trong MongoDB ... đó là một cách sử dụng rất phổ biến (tôi sử dụng nó nhiều hơn một nơi trong sản xuất và nó hoạt động khá tốt.)
Justin Jenkins

2
Tôi có lẽ đã quá nghiêm khắc trong câu trả lời của tôi. Không có gì sai trong việc lưu trữ các bài đăng trên blog và các bình luận liên quan trong MongoDB hoặc cơ sở dữ liệu tương tự. Mọi người thường có xu hướng lạm dụng các cơ sở dữ liệu dựa trên tài liệu (ví dụ cơ bản nhất là lưu trữ tất cả dữ liệu của bạn trong một tài liệu duy nhất gọi là 'blog')
Mchl

3
@Mchel: "blog" không tốt, nhưng lưu trữ bình luận trong một bộ sưu tập riêng biệt cũng tệ như vậy vì những lý do tương tự. Các bài viết với một mảng bình luận là như thế, ví dụ đại bác của một tài liệu db.
Matt Briggs

6
@SoP People: lưu trữ các bình luận trong một bài đăng giống như ví dụ điển hình của các DB hướng tài liệu. (giống như lưu trữ toàn bộ văn bản wiki bên trong một tài liệu) Nếu tôi viết SO, nó sẽ chạy hoàn toàn trên MongoDB. Không ai trong số những mục SO sẽ hợp lý quá 4MB. Craigslist đang thực hiện một cuộc di cư DB khổng lồ trong lịch sử của họ sang MongoDB. Họ chỉ có một vài tài liệu vượt quá giới hạn đó và nhà phát triển chính cho rằng chính các tài liệu đó đã thực sự bị phá vỡ (kết quả của một số lỗi). Một lần nữa, 4 megs là một vài cuốn tiểu thuyết.
Gates VP

3
@Gates VP, tôi đồng ý về việc sử dụng một công cụ toàn văn riêng biệt. Tôi đã suy nghĩ về một tìm kiếm siêu dữ liệu. Điều gì sẽ xảy ra nếu bạn có một bộ tài liệu Sách và bạn muốn tìm tất cả các sách được xuất bản vào năm 1982? Nếu mỗi cuốn sách có hơn 100kb văn bản, bạn không muốn chuyển vài megabyte chỉ để hiển thị 20 tên sách đầu tiên.
mikerobi

0

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

Nếu bạn cho rằng một bài đăng trên blog có thể vượt quá giới hạn tài liệu 16Mb, bạn nên trích xuất các nhận xét thành một bộ sưu tập riêng và tham khảo bài đăng trên blog từ nhận xét và tham gia ở cấp độ ứng dụng.

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

// comments
[
  {
    text: 'a comment'
    post: ObjectID('AAAA')
  },
  {
    text: 'another comment'
    post: ObjectID('AAAA')
  }
]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.