Như đã viết, không có quy tắc nào giống như biểu mẫu thông thường thứ hai cho SQL.
Tuy nhiên, có một số phương pháp hay nhất và những cạm bẫy phổ biến liên quan đến việc tối ưu hóa cho MongoDB mà tôi sẽ liệt kê ở đây.
Lạm dụng nhúng
Giới hạn BSON
Trái ngược với niềm tin phổ biến, không có gì sai khi tham khảo. Giả sử bạn có một thư viện sách và bạn muốn theo dõi việc cho thuê. Bạn có thể bắt đầu với một mô hình như thế này
{
// We use ISBN for its uniqueness
_id: "9783453031456"
title: "Schismatrix",
author: "Bruce Sterling",
rentals: [
{
name:"Markus Mahlberg,
start:"2015-05-05T03:22:00Z",
due:"2015-05-12T12:00:00Z"
}
]
}
Mặc dù có một số vấn đề với mô hình này, nhưng điều quan trọng nhất không rõ ràng - sẽ có số lượng cho thuê hạn chế vì thực tế là tài liệu BSON có giới hạn kích thước là 16MB.
Sự cố di chuyển tài liệu
Một vấn đề khác với việc lưu trữ tài liệu cho thuê trong một mảng là điều này sẽ gây ra việc di chuyển tài liệu tương đối thường xuyên, đây là một hoạt động khá tốn kém. Tài liệu BSON không bao giờ được phân vùng và được tạo với một số không gian bổ sung được phân bổ trước được sử dụng khi chúng phát triển. Khoảng trống bổ sung này được gọi là khoảng đệm. Khi vùng đệm bị vượt quá, tài liệu sẽ được chuyển đến vị trí khác trong tệp dữ liệu và không gian đệm mới được cấp phát. Vì vậy, việc bổ sung dữ liệu thường xuyên gây ra việc di chuyển tài liệu thường xuyên.
Vì vậy, ví dụ, chúng tôi sẽ thay đổi mô hình duy nhất của mình và tạo mô hình thứ hai. Đầu tiên, mô hình cho cuốn sách
{
_id: "9783453031456",
title:"Schismatrix",
author: "Bruce Sterling"
}
Mô hình thứ hai cho việc cho thuê sẽ trông như thế này
{
_id: new ObjectId(),
book: "9783453031456",
rentee: "Markus Mahlberg",
start: ISODate("2015-05-05T03:22:00Z"),
due: ISODate("2015-05-05T12:00:00Z"),
returned: ISODate("2015-05-05T11:59:59.999Z")
}
Tất nhiên có thể sử dụng phương pháp tương tự cho tác giả hoặc người cho thuê.
Sự cố với quá trình chuẩn hóa
Chúng ta hãy nhìn lại một thời gian. Một nhà phát triển sẽ xác định các thực thể liên quan trong một trường hợp kinh doanh, xác định thuộc tính và quan hệ của chúng, viết các lớp thực thể theo, đập đầu vào tường trong vài giờ để làm cho bộ ba bên trong-bên ngoài-trên và ngoài JOIN hoạt động cần thiết cho trường hợp sử dụng và tất cả đều sống hạnh phúc mãi mãi. Vậy tại sao lại sử dụng NoSQL nói chung và MongoDB nói riêng? Bởi vì không ai sống hạnh phúc mãi mãi. Cách tiếp cận này quy mô khủng khiếp và hầu như chỉ có một cách duy nhất để mở rộng quy mô là theo chiều dọc.
Nhưng điểm khác biệt chính của NoSQL là bạn lập mô hình dữ liệu của mình theo các câu hỏi bạn cần được trả lời.
Nói như vậy, chúng ta hãy xem xét một mối quan hệ n:m điển hình và lấy mối quan hệ từ tác giả đến sách làm ví dụ của chúng ta. Trong SQL, bạn có 3 bảng:hai bảng cho các thực thể của bạn ( sách và tác giả ) và một cho mối quan hệ ( Ai là tác giả của cuốn sách nào? ). Tất nhiên, bạn có thể lấy các bảng đó và tạo các bộ sưu tập tương đương của chúng. Tuy nhiên, vì không có JOIN trong MongoDB, bạn cần ba truy vấn (một cho thực thể đầu tiên, một cho các quan hệ của nó và một cho các thực thể liên quan) để tìm các tài liệu liên quan của một thực thể. Điều này sẽ không có ý nghĩa, vì phương pháp tiếp cận ba bảng cho quan hệ n:m được phát minh đặc biệt để vượt qua các lược đồ nghiêm ngặt mà cơ sở dữ liệu SQL thực thi. phát sinh từ việc lạm dụng nhúng trong tâm trí. Vì một tác giả có thể viết khá nhiều sách trong những năm tới, nhưng quyền tác giả của một cuốn sách hiếm khi thay đổi, câu trả lời rất đơn giản:Chúng tôi lưu trữ các tác giả để tham khảo các tác giả trong dữ liệu sách
{
_id: "9783453526723",
title: "The Difference Engine",
authors: ["idOfBruceSterling","idOfWilliamGibson"]
}
Và bây giờ chúng tôi có thể tìm tác giả của cuốn sách đó bằng cách thực hiện hai truy vấn:
var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})
Tôi hy vọng những điều trên sẽ giúp bạn quyết định khi nào thực sự "chia nhỏ" bộ sưu tập của mình và giải quyết những cạm bẫy phổ biến nhất.
Kết luận
Đối với câu hỏi của bạn, đây là câu trả lời của tôi
- Như đã viết trước đây: Không , nhưng lưu ý các giới hạn kỹ thuật sẽ giúp bạn biết khi nào nó có thể có ý nghĩa.
- Nó không tệ - miễn là nó phù hợp với (các) trường hợp sử dụng của bạn . Nếu bạn có một danh mục nhất định và
_id
của nó , rất dễ dàng để tìm thấy các sản phẩm liên quan. Khi tải sản phẩm, bạn có thể dễ dàng nhận được các danh mục mà sản phẩm thuộc về, thậm chí hiệu quả như vậy, như_id
được lập chỉ mục theo mặc định. - Tôi vẫn chưa tìm thấy trường hợp sử dụng nào không thể thực hiện được với MongoDB, mặc dù một số thứ có thể phức tạp hơn một chút với MongoDB. Những gì bạn nên làm imho là lấy tổng các yêu cầu chức năng và phi chức năng của bạn và kiểm tra kỹ hơn những ưu điểm vượt trội so với nhược điểm. Quy tắc chung của tôi:nếu một trong số "khả năng mở rộng" hoặc "tính khả dụng cao / chuyển đổi dự phòng tự động" nằm trong danh sách các yêu cầu của bạn, thì MongoDB đáng để xem xét hơn.