Dữ liệu được lưu trữ trong ví dụ mongodb như thế nào?

Tài liệu này phác thảo các mẫu và nguyên tắc cơ bản để sử dụng MongoDB làm công cụ lưu trữ liên tục cho dữ liệu nhật ký từ máy chủ và dữ liệu máy khác

Vấn đề¶

Máy chủ tạo ra một số lượng lớn các sự kiện (i. e. ghi nhật ký), chứa thông tin hữu ích về hoạt động của chúng bao gồm lỗi, cảnh báo và hành vi của người dùng. Theo mặc định, hầu hết các máy chủ, lưu trữ những dữ liệu này trong tệp nhật ký văn bản thuần túy trên hệ thống tệp cục bộ của chúng

Mặc dù nhật ký văn bản thuần túy có thể truy cập và con người có thể đọc được, nhưng chúng khó sử dụng, tham khảo và phân tích nếu không có hệ thống tổng thể để tổng hợp và lưu trữ những dữ liệu này

Dung dịch¶

Giải pháp được mô tả bên dưới giả định rằng mỗi máy chủ tạo sự kiện cũng sử dụng dữ liệu sự kiện và mỗi máy chủ có thể truy cập phiên bản MongoDB. Hơn nữa, thiết kế này giả định rằng tốc độ truy vấn cho dữ liệu ghi nhật ký này thấp hơn đáng kể so với mức phổ biến đối với các ứng dụng ghi nhật ký có luồng sự kiện băng thông cao

注解

Trường hợp này giả định rằng bạn đang sử dụng bộ sưu tập tiêu chuẩn chưa khai thác cho dữ liệu sự kiện này, trừ khi có ghi chú khác. Xem phần về bộ sưu tập giới hạn

Thiết kế giản đồ¶

Lược đồ lưu trữ dữ liệu nhật ký trong MongoDB tùy thuộc vào định dạng của dữ liệu sự kiện mà bạn đang lưu trữ. Đối với một ví dụ đơn giản, hãy xem xét các bản ghi yêu cầu tiêu chuẩn ở định dạng kết hợp từ Máy chủ HTTP Apache. Một dòng từ các nhật ký này có thể giống như sau

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"

Cách tiếp cận đơn giản nhất để lưu trữ dữ liệu nhật ký là đưa văn bản chính xác của bản ghi nhật ký vào tài liệu

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}

Mặc dù giải pháp này thu thập tất cả dữ liệu ở định dạng mà MongoDB có thể sử dụng, nhưng dữ liệu không đặc biệt hữu ích hoặc không hiệu quả lắm. nếu bạn cần tìm các sự kiện trên cùng một trang, bạn sẽ cần sử dụng truy vấn biểu thức chính quy, truy vấn này sẽ yêu cầu quét toàn bộ bộ sưu tập. Cách tiếp cận ưa thích là trích xuất thông tin liên quan từ dữ liệu nhật ký vào các trường riêng lẻ trong tài liệu MongoDB

Khi bạn trích xuất dữ liệu từ nhật ký vào các trường, hãy chú ý đến các loại dữ liệu bạn sử dụng để hiển thị dữ liệu nhật ký vào MongoDB

Khi bạn thiết kế lược đồ này, hãy lưu ý rằng các loại dữ liệu bạn sử dụng để mã hóa dữ liệu có thể có tác động đáng kể đến hiệu suất và khả năng của hệ thống ghi nhật ký. Xem xét trường ngày. Trong ví dụ trên, [10/Oct/2000. 13. 55. 36 -0700] dài 28 byte. Nếu bạn lưu trữ thông tin này với loại dấu thời gian UTC, bạn có thể truyền tải thông tin tương tự chỉ trong 8 byte.

Ngoài ra, việc sử dụng các loại thích hợp cho dữ liệu của bạn cũng làm tăng tính linh hoạt của truy vấn. nếu bạn lưu trữ ngày dưới dạng dấu thời gian, bạn có thể thực hiện truy vấn phạm vi ngày, trong khi rất khó để so sánh hai chuỗi đại diện cho ngày. Vấn đề tương tự cũng xảy ra đối với các trường số;

Xem xét tài liệu sau thu thập tất cả dữ liệu từ mục nhập nhật ký ở trên

{
     _id: ObjectId('4f442120eb03305789000000'),
     host: "127.0.0.1",
     logname: null,
     user: 'frank',
     time: ISODate("2000-10-10T20:55:36Z"),
     path: "/apache_pb.gif",
     request: "GET /apache_pb.gif HTTP/1.0",
     status: 200,
     response_size: 2326,
     referrer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
     user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
}

Khi trích xuất dữ liệu từ nhật ký và thiết kế lược đồ, hãy xem xét những thông tin nào bạn có thể bỏ qua khỏi hệ thống theo dõi nhật ký của mình. Trong hầu hết các trường hợp, không cần theo dõi tất cả dữ liệu từ nhật ký sự kiện và bạn có thể bỏ qua các trường khác. Để tiếp tục ví dụ trên, ở đây thông tin quan trọng nhất có thể là máy chủ, thời gian, đường dẫn, tác nhân người dùng và liên kết giới thiệu, như trong tài liệu ví dụ sau

{
     _id: ObjectId('4f442120eb03305789000000'),
     host: "127.0.0.1",
     time:  ISODate("2000-10-10T20:55:36Z"),
     path: "/apache_pb.gif",
     referer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
     user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
}

Bạn cũng có thể cân nhắc bỏ qua các trường thời gian rõ ràng vì ObjectId nhúng thời gian tạo.

{
     _id: ObjectId('4f442120eb03305789000000'),
     host: "127.0.0.1",
     path: "/apache_pb.gif",
     referer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
     user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
}

Kiến Trúc Hệ Thống¶

Mối quan tâm chính về hiệu suất đối với các hệ thống ghi nhật ký sự kiện là

  1. nó có thể hỗ trợ bao nhiêu lần chèn mỗi giây, giới hạn thông lượng sự kiện và

  2. hệ thống sẽ quản lý sự phát triển của dữ liệu sự kiện như thế nào, đặc biệt liên quan đến sự phát triển trong hoạt động chèn

    Trong hầu hết các trường hợp, cách tốt nhất để tăng dung lượng của hệ thống là sử dụng một kiến ​​trúc với một số loại phân vùng hoặc phân mảnh để phân phối ghi giữa một cụm hệ thống

Vận hành¶

Tốc độ chèn là mối quan tâm chính về hiệu suất đối với hệ thống ghi nhật ký sự kiện. Đồng thời hệ thống phải hỗ trợ truy vấn linh hoạt để bạn có thể trả về dữ liệu từ hệ thống một cách hiệu quả. Phần này mô tả quy trình cho cả truy vấn chèn tài liệu và phân tích cơ bản

Các ví dụ sau sử dụng ngôn ngữ lập trình Python và trình điều khiển PyMongo cho MongoDB, nhưng bạn có thể triển khai hệ thống này bằng bất kỳ ngôn ngữ nào bạn chọn

Chèn một bản ghi nhật ký¶

Viết mối quan tâm¶

MongoDB có mối quan tâm ghi có thể định cấu hình. Khả năng này cho phép bạn cân bằng tầm quan trọng của việc đảm bảo rằng tất cả các thao tác ghi được ghi đầy đủ vào cơ sở dữ liệu với tốc độ chèn

Ví dụ: nếu bạn thực hiện ghi vào MongoDB và không yêu cầu cơ sở dữ liệu đưa ra bất kỳ phản hồi nào, thì các thao tác ghi sẽ trở lại rất nhanh (i. e. không đồng bộ,) nhưng bạn không thể chắc chắn rằng tất cả các thao tác ghi đều thành công. Ngược lại, nếu bạn yêu cầu MongoDB xác nhận mọi thao tác ghi, cơ sở dữ liệu sẽ không trả về nhanh như vậy nhưng bạn có thể chắc chắn rằng mọi mục sẽ có mặt trong cơ sở dữ liệu

Mối quan tâm ghi thích hợp thường là một quyết định cụ thể của ứng dụng và phụ thuộc vào các yêu cầu báo cáo và việc sử dụng ứng dụng phân tích của bạn

Chèn hiệu suất¶

Ví dụ sau chứa thiết lập cho phiên bảng điều khiển Python bằng PyMongo, với một sự kiện từ Nhật ký Apache

>>> import bson
>>> import pymongo
>>> from datetime import datetime
>>> conn = pymongo.Connection()
>>> db = conn.event_db
>>> event = {
..     _id: bson.ObjectId(),
..     host: "127.0.0.1",
..     time:  datetime(2000,10,10,20,55,36),
..     path: "/apache_pb.gif",
..     referer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
..     user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
...}

Lệnh sau sẽ chèn đối tượng sự kiện vào sự kiện collection.

>>> db.events.insert(event, w=0)

Bằng cách thiết lập w=0 , bạn không yêu cầu MongoDB xác nhận đã nhận phần chèn. Mặc dù rất nhanh, nhưng điều này có rủi ro vì ứng dụng không thể phát hiện lỗi mạng và máy chủ. Xem Viết mối quan tâm để biết thêm thông tin.

Nếu bạn muốn đảm bảo rằng MongoDB thừa nhận các phần chèn, bạn có thể chuyển đối số w=1 như sau.

>>> db.events.insert(event, w=1)

MongoDB cũng hỗ trợ mức độ quan tâm ghi nghiêm ngặt hơn, nếu bạn có khả năng chịu mất dữ liệu thấp hơn

Bạn có thể đảm bảo rằng MongoDB không chỉ xác nhận đã nhận được thông báo mà còn thực hiện thao tác ghi vào nhật ký trên đĩa trước khi quay lại thành công ứng dụng, bạn có thể sử dụng cách sau . operation:

________số 8

注解

j=True ngụ ý w=1 .

Cuối cùng, nếu bạn có khả năng chịu đựng mất dữ liệu sự kiện cực kỳ thấp, bạn có thể yêu cầu MongoDB sao chép dữ liệu thành nhiều thành viên bộ bản sao thứ cấp trước khi quay lại

>>> db.events.insert(event, w=majority)

Điều này sẽ buộc ứng dụng của bạn thừa nhận rằng dữ liệu đã được sao chép tới phần lớn các thành viên được định cấu hình của bộ bản sao. Bạn cũng có thể kết hợp các tùy chọn

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
0

Trong trường hợp này, ứng dụng của bạn sẽ đợi một cam kết nhật ký thành công trên chính và xác nhận sao chép từ phần lớn các phụ được định cấu hình. Đây là tùy chọn an toàn nhất được trình bày trong phần này, nhưng nó là tùy chọn chậm nhất. Luôn có sự đánh đổi giữa an toàn và tốc độ

注解

Nếu có thể, hãy cân nhắc sử dụng tính năng chèn số lượng lớn để chèn dữ liệu sự kiện

Tất cả tùy chọn ghi mối quan tâm áp dụng cho chèn hàng loạt, nhưng bạn có thể chuyển nhiều sự kiện cho phương thức insert() cùng một lúc. Các phần chèn hàng loạt cho phép MongoDB phân phối hình phạt hiệu suất phát sinh do mối quan tâm ghi nghiêm ngặt hơn trên một nhóm các phần chèn.

也可以参考

“Ghi mối quan tâm cho bộ bản sao” và getLastError .

Tìm tất cả các sự kiện cho một trang cụ thể¶

Giá trị trong việc duy trì bộ sưu tập dữ liệu sự kiện bắt nguồn từ việc có thể truy vấn dữ liệu đó để trả lời các câu hỏi cụ thể. Bạn có thể có một số truy vấn đơn giản mà bạn có thể sử dụng để phân tích những dữ liệu này

Ví dụ, bạn có thể muốn trả về tất cả các sự kiện được liên kết với giá trị cụ thể của một trường. Mở rộng ví dụ nhật ký truy cập Apache ở trên, một trường hợp phổ biến sẽ là truy vấn tất cả các sự kiện có giá trị cụ thể trong trường đường dẫn . Phần này chứa một mẫu để trả về dữ liệu và tối ưu hóa thao tác này.

Truy vấn¶

Sử dụng truy vấn giống như sau để trả về tất cả tài liệu với /apache_pb. giá trị gif trong trường đường dẫn .

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
1

注解

Nếu bạn chọn phân đoạn bộ sưu tập lưu trữ dữ liệu này, khóa phân đoạn bạn chọn có thể ảnh hưởng đến hiệu suất của truy vấn này. Xem phần sharding của tài liệu sharding

Hỗ trợ chỉ mục¶

Việc thêm chỉ mục vào trường đường dẫn sẽ nâng cao đáng kể hiệu suất của thao tác này.

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
2

Vì các giá trị của đường dẫn có khả năng phân phối ngẫu nhiên nên để hoạt động hiệu quả, toàn bộ chỉ mục phải nằm trong RAM. Trong trường hợp này, số lượng đường dẫn riêng biệt thường nhỏ so với số lượng tài liệu, điều này sẽ giới hạn không gian mà chỉ mục yêu cầu.

Nếu hệ thống của bạn có dung lượng RAM hạn chế hoặc tập dữ liệu của bạn có phân phối giá trị rộng hơn, bạn có thể cần điều tra lại hỗ trợ lập chỉ mục của mình. Tuy nhiên, trong hầu hết các trường hợp, chỉ số này là hoàn toàn đủ

也可以参考

Db . thu thập. ensureIndex() Phương thức JavaScript và db. sự kiện. phương thức ensure_index() trong PyMongo.

Tìm tất cả các sự kiện cho một ngày cụ thể¶

Ví dụ tiếp theo mô tả quy trình trả về tất cả các sự kiện cho một ngày cụ thể

Truy vấn¶

Để truy xuất dữ liệu này, hãy sử dụng truy vấn sau

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
3

Hỗ trợ chỉ mục¶

Trong trường hợp này, một chỉ mục trên trường thời gian sẽ tối ưu hóa hiệu suất.

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
4

Bởi vì ứng dụng của bạn đang chèn các sự kiện theo thứ tự, các phần của chỉ mục nắm bắt các sự kiện gần đây sẽ luôn ở trong RAM hoạt động. Do đó, nếu bạn truy vấn chủ yếu trên dữ liệu gần đây, MongoDB sẽ có thể duy trì một chỉ mục lớn, thực hiện nhanh các truy vấn và tránh sử dụng nhiều bộ nhớ hệ thống

也可以参考

Db . sự kiện. ensureIndex() Phương thức JavaScript và db. sự kiện. phương thức ensure_index() trong PyMongo.

Tìm tất cả các sự kiện cho một máy chủ/ngày cụ thể¶

Ví dụ sau mô tả một truy vấn phức tạp hơn để trả về tất cả các sự kiện trong bộ sưu tập cho một máy chủ lưu trữ cụ thể vào một ngày cụ thể. Loại phân tích này có thể hữu ích để điều tra hành vi đáng ngờ của một người dùng cụ thể

Truy vấn¶

Sử dụng truy vấn giống như sau

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
5

Truy vấn này chọn tài liệu từ bộ sưu tập sự kiện nơi máy chủ field is 127.0.0.1 (tôi. e. máy chủ cục bộ) và giá trị của trường thời gian biểu thị một ngày vào hoặc sau (i. e. $gte ) 2000-10-10 nhưng trước đó (i. e. $lt ) 2000-10-11 .

Hỗ trợ chỉ mục¶

Các chỉ mục bạn sử dụng có thể có ý nghĩa quan trọng đối với hiệu suất của các loại truy vấn này. Chẳng hạn, bạn có thể tạo chỉ mục tổng hợp trên thời gianmáy chủ .

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
6

Để phân tích hiệu suất cho truy vấn trên bằng chỉ mục này, hãy đưa ra q_events. giải thích() trong bảng điều khiển Python. Điều này sẽ trả lại một cái gì đó giống như.

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
7

Truy vấn này phải quét 1296 mục từ chỉ mục để trả về 11 đối tượng trong 4 mili giây. Ngược lại, trước tiên, bạn có thể kiểm tra một chỉ mục hỗn hợp khác bằng trường máy chủ , sau đó là trường thời gian field. Create this index using the following operation:

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
8

Sử dụng q_events. giải thích() để kiểm tra hiệu suất.

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
9

Ở đây, truy vấn phải quét 11 mục từ chỉ mục trước khi trả về 11 đối tượng trong vòng chưa đầy một phần nghìn giây. Bằng cách đặt phần tử chọn lọc hơn trong truy vấn của bạn trước trong chỉ mục tổng hợp, bạn có thể tạo các truy vấn hữu ích hơn

注解

Mặc dù thứ tự chỉ mục có ảnh hưởng đến hiệu suất truy vấn, hãy nhớ rằng quét chỉ mục nhanh hơn nhiều so với quét bộ sưu tập và tùy thuộc vào các truy vấn khác của bạn, việc sử dụng có thể hợp lý hơn . time: 1, máy chủ. 1 } chỉ mục tùy thuộc vào hồ sơ sử dụng.

也可以参考

Db . sự kiện. ensureIndex() Phương thức JavaScript và db. sự kiện. phương thức ensure_index() trong PyMongo.

Đếm yêu cầu theo ngày và trang¶

Ví dụ sau đây mô tả quy trình sử dụng tập hợp các sự kiện truy cập Apache để xác định số lượng yêu cầu trên mỗi tài nguyên (i. e. trang) mỗi ngày trong tháng trước

tổng hợp¶

2. 1 新版功能

Khung tổng hợp cung cấp khả năng cho các truy vấn chọn, xử lý và tổng hợp kết quả từ số lượng lớn tài liệu. aggregate() cung cấp tính linh hoạt cao hơn, dung lượng ít phức tạp hơn mapReduce and group aggregation commands.

Xem xét đường ống tổng hợp sau. [1]

{
     _id: ObjectId('4f442120eb03305789000000'),
     host: "127.0.0.1",
     logname: null,
     user: 'frank',
     time: ISODate("2000-10-10T20:55:36Z"),
     path: "/apache_pb.gif",
     request: "GET /apache_pb.gif HTTP/1.0",
     status: 200,
     response_size: 2326,
     referrer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
     user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
}
0

Lệnh này tổng hợp các tài liệu từ bộ sưu tập sự kiện với một đường dẫn.

  1. Sử dụng $match để giới hạn các tài liệu mà khung tổng hợp phải xử lý. $match tương tự như truy vấn find() .

    Thao tác này chọn tất cả các tài liệu trong đó giá trị của trường thời gian đại diện cho một ngày vào hoặc sau (i. e. $gte ) 2000-10-10 nhưng trước đó (i. e. $lt ) 2000-10-11 .

  2. Sử dụng $project để giới hạn dữ liệu tiếp tục thông qua đường ống. toán tử này.

    • Chọn trường đường dẫn .
    • Tạo trường y để giữ năm, được tính từ thời gian field in the original documents.
    • Tạo trường m để giữ tháng, được tính từ thời điểm field in the original documents
    • Tạo trường d để giữ ngày, được tính từ thời gian field in the original documents.
  3. Sử dụng $group để tạo tài liệu mới được tính toán. Bước này sẽ tạo một tài liệu mới cho mỗi kết hợp đường dẫn/ngày duy nhất. Các tài liệu có dạng sau.

    • trường _id chứa tài liệu phụ có nội dung đường dẫn field from the original documents in the p field, with the date fields from the $project as the remaining fields.
    • trường lần truy cập sử dụng câu lệnh $sum để . Trong đầu ra tổng hợp, trường này chứa tổng số tài liệu ở đầu quy trình tổng hợp với ngày và đường dẫn duy nhất này.

注解

Trong môi trường phân đoạn, hiệu suất của hoạt động tổng hợp phụ thuộc vào khóa phân đoạn. Lý tưởng nhất là tất cả các mục trong một hoạt động $group cụ thể sẽ nằm trên cùng một máy chủ.

Mặc dù việc phân phối tài liệu này sẽ xảy ra nếu bạn chọn trường thời gian làm khóa phân đoạn, nhưng trường như path also has this property and is a typical choice for sharding. Also see the “sharding considerations.” of this document for additional recommendations for using sharding.

也可以参考

“聚合框架“

[1]Để dịch các câu lệnh từ khung tổng hợp sang SQL, bạn có thể xem xét $match tương đương với WHERE, $project to SELECT, and $group to GROUP BY.

Hỗ trợ chỉ mục¶

Để tối ưu hóa thao tác tổng hợp, hãy đảm bảo rằng truy vấn $match ban đầu có chỉ mục. Sử dụng lệnh sau để tạo chỉ mục trên trường thời gian trong sự kiện collection:

{
  _id: ObjectId('4f442120eb03305789000000'),
 line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
}
4

注解

Nếu bạn đã tạo chỉ mục hỗn hợp trên thời gianmáy chủ (i.e. { thời gian. 1, máy chủ, 1 },) MongoDB will use this index for range queries on just the time field. Do not create an additional index, in these situations.

Chia sẻ¶

Cuối cùng, các sự kiện trong hệ thống của bạn sẽ vượt quá khả năng của một phiên bản cơ sở dữ liệu ghi nhật ký sự kiện. Trong những tình huống này, bạn sẽ muốn sử dụng một cụm được phân đoạn, cụm này tận dụng chức năng phân đoạn của MongoDB. Phần này giới thiệu các mối quan tâm về sharding duy nhất cho trường hợp ghi sự kiện này

也可以参考

分片 and FAQ. 分片

Hạn chế¶

Trong môi trường phân mảnh, giới hạn về tốc độ chèn tối đa là

  • số lượng phân đoạn trong cụm
  • khóa phân đoạn bạn đã chọn

Bởi vì MongoDB đã phân phối dữ liệu bằng cách sử dụng “phạm vi” (i. e. chunks) của khóa, việc lựa chọn khóa phân đoạn có thể kiểm soát cách MongoDB phân phối dữ liệu và khả năng ghi và truy vấn của hệ thống kết quả

Lý tưởng nhất là khóa phân đoạn của bạn sẽ cho phép các lần chèn cân bằng giữa các phân đoạn [2] và đối với hầu hết các truy vấn chỉ cần truy cập vào một phân đoạn duy nhất. [3] Tiếp tục đọc để phân tích bộ sưu tập các lựa chọn chính của phân đoạn

[2]Vì lý do này, hãy tránh khóa phân đoạn dựa trên dấu thời gian hoặc thời gian chèn (i. e. ObjectId ) vì tất cả quá trình ghi sẽ kết thúc trên một nút duy nhất. [3]Vì lý do này, hãy tránh các khóa phân đoạn ngẫu nhiên (e. g. khóa phân đoạn dựa trên hàm băm) vì mọi truy vấn sẽ phải truy cập vào tất cả các phân đoạn trong cụm.

Phân mảnh theo thời gian¶

Trong khi sử dụng dấu thời gian hoặc ObjectId trong _id field, [4] would distribute your data evenly among shards, these keys lead to two problems:

  1. Tất cả các phần chèn luôn chảy vào cùng một phân đoạn, điều đó có nghĩa là cụm phân đoạn của bạn sẽ có cùng thông lượng ghi như một phiên bản độc lập
  2. Hầu hết các lượt đọc sẽ có xu hướng tập trung vào cùng một phân đoạn, vì các truy vấn phân tích
[4]The ObjectId bắt nguồn từ thời gian tạo và thực sự là dấu thời gian trong trường hợp này.

Phân đoạn theo khóa bán ngẫu nhiên¶

Để phân phối dữ liệu đồng đều hơn giữa các phân đoạn, bạn có thể cân nhắc sử dụng một phần dữ liệu "ngẫu nhiên" hơn, chẳng hạn như hàm băm của _id field (i.e. the ObjectId làm khóa phân đoạn.

Mặc dù điều này tạo ra một số phức tạp bổ sung vào ứng dụng của bạn, nhưng để tạo khóa, nó sẽ phân phối ghi giữa các phân đoạn. Trong những lần triển khai này, có 5 phân đoạn sẽ cung cấp khả năng ghi gấp 5 lần dưới dạng một phiên bản

Sử dụng khóa phân đoạn này hoặc bất kỳ giá trị băm nào làm khóa sẽ có những nhược điểm sau

  • khóa phân đoạn và chỉ mục trên khóa sẽ chiếm thêm dung lượng trong cơ sở dữ liệu
  • các truy vấn, trừ khi chúng bao gồm chính khóa phân đoạn, [5] phải chạy song song trên tất cả các phân đoạn, điều này có thể dẫn đến hiệu suất bị suy giảm

Đây có thể là một sự đánh đổi chấp nhận được trong một số tình huống. Khối lượng công việc của các hệ thống ghi sự kiện có xu hướng nghiêng nhiều về ghi, hiệu suất đọc có thể không quan trọng bằng hiệu suất ghi mạnh mẽ hơn

[5]Thông thường, rất khó để sử dụng các loại khóa phân đoạn này trong các truy vấn

Phân đoạn theo Khóa phân bổ đều trong Tập dữ liệu¶

Nếu một trường trong tài liệu của bạn có các giá trị được phân bổ đồng đều giữa các tài liệu, bạn có thể cân nhắc sử dụng khóa này làm khóa phân đoạn

Tiếp tục ví dụ ở trên, bạn có thể cân nhắc sử dụng trường đường dẫn . Mà có thể có một vài lợi thế.

  1. ghi sẽ có xu hướng cân bằng đồng đều giữa các mảnh
  2. các lần đọc sẽ có xu hướng chọn lọc và cục bộ vào một phân đoạn duy nhất nếu truy vấn chọn trên trường đường dẫn .

Có một số vấn đề tiềm ẩn với các loại khóa phân đoạn này

  1. Nếu một số lượng lớn tài liệu sẽ có cùng một khóa phân đoạn, bạn sẽ gặp rủi ro khi một phần bộ sưu tập dữ liệu MongoDB của bạn không thể phân phối trên toàn cụm
  2. Nếu có một số lượng nhỏ các giá trị có thể, thì có thể có giới hạn về số lượng MongoDB có thể phân phối dữ liệu giữa các phân đoạn

注解

Kiểm tra bằng cách sử dụng dữ liệu hiện có của bạn để đảm bảo rằng phân phối thực sự đồng đều và có đủ số lượng giá trị riêng biệt cho khóa phân đoạn

Phân đoạn bằng cách kết hợp khóa tự nhiên và khóa tổng hợp¶

MongoDB hỗ trợ các khóa phân đoạn phức hợp kết hợp các khía cạnh tốt nhất của quá trình phân đoạn bằng một khóa phân bổ đều trong tập hợp và phân đoạn theo một khóa ngẫu nhiên. Trong những trường hợp này, khóa phân đoạn sẽ giống như { path. 1 , ssk. 1 } ở đâu, đường dẫn . [6] ssk is a hash of the _id field. [6]

Khi sử dụng loại khóa phân đoạn này, phần lớn dữ liệu được phân phối theo khóa tự nhiên hoặc đường dẫn , khiến hầu hết các truy vấn truy cập vào < . Đồng thời, nếu không có đủ phân phối cho các giá trị cụ thể của path field local to a single shard or group of shards. At the same time, if there is not sufficient distribution for specific values of đường dẫn , thì ssk makes it possible for MongoDB to create chunks and data across the cluster.

Trong hầu hết các trường hợp, các loại khóa này cung cấp sự cân bằng lý tưởng giữa việc phân phối ghi trên cụm và đảm bảo rằng hầu hết các truy vấn sẽ chỉ cần truy cập vào một số phân đoạn được chọn

[6]Bạn vẫn phải tính toán giá trị của khóa tổng hợp này trong ứng dụng của mình khi bạn chèn tài liệu vào bộ sưu tập của mình

Thử nghiệm với dữ liệu của chính bạn¶

Việc chọn shard key rất khó vì. không có "phương pháp hay nhất" dứt khoát nào, quyết định có tác động lớn đến hiệu suất và rất khó hoặc không thể thay đổi khóa phân đoạn sau khi thực hiện lựa chọn

Các tùy chọn phân đoạn cung cấp một điểm khởi đầu tốt để suy nghĩ về lựa chọn khóa phân đoạn. Tuy nhiên, cách tốt nhất để chọn khóa phân đoạn là phân tích các lần chèn và truy vấn thực tế từ ứng dụng của riêng bạn

Quản lý tăng trưởng dữ liệu sự kiện¶

Nếu không có một số chiến lược để quản lý kích thước cơ sở dữ liệu của bạn, hầu hết các hệ thống ghi sự kiện có thể phát triển vô hạn. Điều này đặc biệt quan trọng trong bối cảnh MongoDB có thể không từ bỏ dữ liệu vào hệ thống tệp theo cách bạn mong đợi. Xem xét các chiến lược sau để quản lý tăng trưởng dữ liệu

Bộ sưu tập giới hạn¶

Tùy thuộc vào yêu cầu lưu giữ dữ liệu cũng như nhu cầu báo cáo và phân tích của bạn, bạn có thể cân nhắc sử dụng bộ sưu tập giới hạn để lưu trữ các sự kiện của mình. Các bộ sưu tập giới hạn có kích thước cố định và loại bỏ dữ liệu cũ khi chèn dữ liệu mới sau khi đạt đến giới hạn

注解

Trong phiên bản hiện tại, không thể chia nhỏ các bộ sưu tập đã giới hạn

Nhiều bộ sưu tập, một cơ sở dữ liệu¶

Chiến lược. Định kỳ đổi tên bộ sưu tập sự kiện của bạn để bộ sưu tập dữ liệu của bạn xoay vòng giống như cách bạn có thể xoay tệp nhật ký. Khi cần, bạn có thể xóa bộ sưu tập cũ nhất khỏi cơ sở dữ liệu

Cách tiếp cận này có một số lợi thế so với cách tiếp cận bộ sưu tập duy nhất

  1. Đổi tên bộ sưu tập nhanh và nguyên tử
  2. MongoDB không đưa bất kỳ tài liệu nào vào bộ nhớ để xóa bộ sưu tập
  3. MongoDB có thể tái sử dụng hiệu quả không gian được giải phóng bằng cách xóa toàn bộ bộ sưu tập mà không dẫn đến phân mảnh dữ liệu

Tuy nhiên, thao tác này có thể làm tăng độ phức tạp cho các truy vấn, nếu bất kỳ phân tích nào của bạn phụ thuộc vào các sự kiện có thể nằm trong bộ sưu tập hiện tại và trước đó. Đối với hầu hết các hệ thống thu thập dữ liệu thời gian thực, cách tiếp cận này là lý tưởng nhất

Nhiều cơ sở dữ liệu¶

Chiến lược. Xoay cơ sở dữ liệu thay vì bộ sưu tập, như trong ví dụ “Nhiều bộ sưu tập, Cơ sở dữ liệu đơn

Mặc dù điều này làm tăng đáng kể độ phức tạp của ứng dụng đối với các lần chèn và truy vấn, nhưng khi bạn xóa cơ sở dữ liệu cũ, MongoDB sẽ trả lại dung lượng ổ đĩa cho hệ thống tệp. Cách tiếp cận này có ý nghĩa nhất trong các tình huống mà tỷ lệ chèn sự kiện và/hoặc tỷ lệ lưu giữ dữ liệu của bạn rất khác nhau

Ví dụ: nếu bạn đang thực hiện chèn lấp một lượng lớn dữ liệu sự kiện và muốn đảm bảo rằng toàn bộ bộ dữ liệu sự kiện trong 90 ngày có sẵn trong quá trình chèn lấp, thì trong các hoạt động bình thường, bạn chỉ cần dữ liệu sự kiện trong 30 ngày, thì bạn có thể cân nhắc sử dụng

Các bản ghi được lưu trữ trong MongoDB như thế nào?

MongoDB lưu trữ các bản ghi dữ liệu dưới dạng tài liệu (cụ thể là tài liệu BSON) được tập hợp lại với nhau trong các bộ sưu tập . Cơ sở dữ liệu lưu trữ một hoặc nhiều bộ sưu tập tài liệu.

MongoDB là gì và ví dụ?

MongoDB cho phép cấu trúc tài liệu có khả năng mở rộng và linh hoạt cao . Ví dụ: một tài liệu dữ liệu của một bộ sưu tập trong MongoDB có thể có hai trường trong khi tài liệu khác trong cùng một bộ sưu tập có thể có bốn trường. MongoDB nhanh hơn so với RDBMS do các kỹ thuật lưu trữ và lập chỉ mục hiệu quả.

MongoDB lưu trữ dữ liệu của nó ở đâu?

Theo mặc định, Mongo lưu trữ dữ liệu của nó trong thư mục /data/db . Bạn có thể chỉ định một thư mục khác bằng tùy chọn --dbpath. Nếu bạn đang chạy Mongo trên Windows thì thư mục sẽ là C. \data\db , trong đó C là ký tự ổ đĩa của thư mục làm việc mà Mongo đã được bắt đầu.

MongoDB tổ chức dữ liệu của nó như thế nào?

MongoDB sử dụng BSON để lưu trữ thông tin . BSON (sự kết hợp của "nhị phân" và "JSON" hoặc Ký hiệu đối tượng JavaScript) có thể được coi là biểu diễn nhị phân hoặc số của tài liệu JSON. JSON là định dạng chuẩn mở (như mã nguồn mở) để tổ chức dữ liệu.