Khi MongoDB được giới thiệu, tính năng chính được đánh dấu là khả năng "không có chữ". Nó có nghĩa là gì? Nó có nghĩa là người ta có thể lưu trữ các tài liệu JSON, mỗi tài liệu có cấu trúc khác nhau, trong cùng một bộ sưu tập. Cái này hay đấy. Nhưng vấn đề bắt đầu khi bạn cần lấy lại các tài liệu. Làm thế nào để bạn biết rằng một tài liệu được truy xuất có cấu trúc nhất định, hoặc liệu nó có chứa một trường cụ thể hay không? Bạn phải lặp lại tất cả các tài liệu và tìm kiếm trường cụ thể đó. Đây là lý do hữu ích khi lập kế hoạch cẩn thận cho lược đồ MongoDB, đặc biệt là đối với các ứng dụng lớn.
Khi nói đến MongoDB, không có cách cụ thể nào để thiết kế lược đồ. Tất cả phụ thuộc vào ứng dụng của bạn và cách ứng dụng của bạn sẽ sử dụng dữ liệu. Tuy nhiên, có một số thực hành phổ biến mà bạn có thể làm theo khi thiết kế lược đồ cơ sở dữ liệu của mình. Ở đây, tôi sẽ thảo luận về những thực hành này và những ưu và nhược điểm của chúng.
Lập mô hình một-vài (Nhúng)
Thiết kế này là một ví dụ rất tốt về việc nhúng tài liệu. Hãy xem xét ví dụ này về tập hợp Người để minh họa mô hình này.
{
name: "Amy Cooper",
hometown: "Seoul",
addresses: [
{ city: 'New York', state: 'NY', cc: 'USA' },
{ city: 'Jersey City', state: 'NJ', cc: 'USA' }
]
}
Ưu điểm:
- Bạn có thể nhận được tất cả thông tin trong một truy vấn.
Nhược điểm:
- Dữ liệu được nhúng hoàn toàn phụ thuộc vào tài liệu mẹ. Bạn không thể tìm kiếm dữ liệu nhúng một cách độc lập.
- Hãy xem xét ví dụ mà bạn đang tạo một hệ thống theo dõi nhiệm vụ bằng cách sử dụng phương pháp này. Sau đó, bạn sẽ nhúng tất cả các nhiệm vụ cụ thể cho một người vào bộ sưu tập Người. Nếu bạn muốn kích hoạt một truy vấn như:Cho tôi xem tất cả các nhiệm vụ có ngày mai là hạn chót. Điều này có thể rất khó, mặc dù nó là một truy vấn đơn giản. Trong trường hợp này, bạn nên xem xét các cách tiếp cận khác.
Mô hình một-nhiều (Tham khảo)
Trong kiểu mô hình hóa này, tài liệu mẹ sẽ giữ Id tham chiếu (ObjectID) của các tài liệu con. Bạn cần sử dụng phép nối cấp ứng dụng (kết hợp hai tài liệu sau khi truy xuất chúng từ DB ở cấp ứng dụng) để truy xuất tài liệu, vì vậy không có cấp cơ sở dữ liệu nào tham gia. Do đó, tải trên cơ sở dữ liệu sẽ được giảm bớt. Hãy xem xét ví dụ này:
// Parts collection
{
_id: ObjectID(1234),
partno: '1',
name: ‘Intel 100 Ghz CPU',
qty: 100,
cost: 1000,
price: 1050
}
// Products collection
{
name: 'Computer WQ-1020',
manufacturer: 'ABC Company',
catalog_number: 1234,
parts: [
ObjectID(‘1234’), <- Ref. for Part No: 1
ObjectID('2345'),
ObjectID('3456')
]
}
Giả sử mỗi sản phẩm có thể có vài nghìn bộ phận liên kết với nó. Đối với loại cơ sở dữ liệu này, tham chiếu là loại mô hình lý tưởng. Bạn đặt id tham chiếu của tất cả các bộ phận liên quan trong tài liệu sản phẩm. Sau đó, bạn có thể sử dụng các phép nối cấp ứng dụng để lấy các bộ phận cho một sản phẩm cụ thể.
Ưu điểm:
- Trong loại mô hình này, mỗi phần là một tài liệu riêng biệt để bạn có thể áp dụng tất cả các truy vấn liên quan đến phần trên các tài liệu này. Không cần phụ thuộc vào tài liệu gốc.
- Rất dễ dàng thực hiện các thao tác CRUD (Tạo, Đọc, Cập nhật, Viết) trên mỗi tài liệu một cách độc lập.
Nhược điểm:
- Một nhược điểm lớn của phương pháp này là bạn phải thực hiện thêm một truy vấn để lấy chi tiết bộ phận. Vì vậy, bạn có thể thực hiện kết hợp cấp ứng dụng với tài liệu sản phẩm để có được tập hợp kết quả cần thiết. Vì vậy, nó có thể dẫn đến giảm hiệu suất DB.
Lập mô hình một đến hàng triệu (Tham khảo ý kiến của phụ huynh)
Khi bạn cần lưu trữ hàng tấn dữ liệu trong mỗi tài liệu, bạn không thể sử dụng bất kỳ phương pháp nào ở trên vì MongoDB có giới hạn kích thước là 16 MB cho mỗi tài liệu. Một ví dụ hoàn hảo cho loại kịch bản này có thể là hệ thống ghi nhật ký sự kiện thu thập nhật ký từ các loại máy khác nhau và lưu trữ chúng trong bộ sưu tập Nhật ký và Máy.
Tại đây, bạn thậm chí không thể nghĩ đến việc sử dụng phương pháp Nhúng lưu trữ tất cả thông tin nhật ký cho một máy cụ thể trong một tài liệu duy nhất. Điều này là do chỉ trong vài giờ nữa, kích thước tài liệu sẽ hơn 16MB. Ngay cả khi bạn chỉ lưu trữ id tham chiếu của tất cả tài liệu nhật ký, bạn vẫn sẽ sử dụng hết giới hạn 16 MB vì một số máy có thể tạo hàng triệu thông báo nhật ký trong một ngày.
Vì vậy, trong trường hợp này, chúng ta có thể sử dụng phương pháp tham chiếu gốc. Trong cách tiếp cận này, thay vì lưu trữ id tham chiếu của tài liệu con trong tài liệu mẹ, chúng tôi sẽ lưu trữ id tham chiếu của tài liệu mẹ trong tất cả tài liệu con. Vì vậy, đối với ví dụ của chúng tôi, chúng tôi sẽ lưu trữ ObjectID của máy trong tài liệu Nhật ký. Hãy xem xét ví dụ này:
// Machines collection
{
_id : ObjectID('AAA'),
name : 'mydb.example.com',
ipaddr : '127.66.0.4'
}
// Logs collection
{
time : ISODate("2015-09-02T09:10:09.032Z"),
message : 'WARNING: CPU usage is critical!',
host: ObjectID('AAA') -> references Machine document
}
Giả sử bạn muốn tìm 3000 bản ghi gần đây nhất của Máy 127.66.0.4:
machine = db.machines.findOne({ipaddr : '127.66.0.4'});
msgs = db.logmsg.find({machine: machine._id}).sort({time : -1}).limit(3000).toArray()
Tham chiếu hai chiều
Theo cách tiếp cận này, chúng tôi lưu trữ các tham chiếu ở cả hai phía, có nghĩa là, tham chiếu của cha mẹ sẽ được lưu trữ trong tài liệu con và tham chiếu của con sẽ được lưu trữ trong tài liệu mẹ. Điều này làm cho việc tìm kiếm tương đối dễ dàng trong một hoặc nhiều mô hình. Ví dụ:chúng ta có thể tìm kiếm trên cả tài liệu mẹ và tài liệu nhiệm vụ, mặt khác, phương pháp này yêu cầu hai truy vấn riêng biệt để cập nhật một tài liệu.
// person
{
_id: ObjectID("AAAA"),
name: "Bear",
tasks [
ObjectID("AAAD"),
ObjectID("ABCD"), -> Reference of child document
ObjectID("AAAB")
]
}
// tasks
{
_id: ObjectID("ABCD"),
description: "Read a Novel",
due_date: ISODate("2015-11-01"),
owner: ObjectID("AAAA") -> Reference of parent document
}
Kết luận
Cuối cùng, tất cả phụ thuộc vào yêu cầu ứng dụng của bạn. Bạn có thể thiết kế lược đồ MongoDB theo cách có lợi nhất cho ứng dụng của bạn và mang lại cho bạn hiệu suất cao. Dưới đây là một số cân nhắc tóm tắt mà bạn có thể cân nhắc khi thiết kế lược đồ của mình.
- Thiết kế giản đồ dựa trên các mẫu truy cập dữ liệu của ứng dụng của bạn.
- Không cần thiết phải nhúng tài liệu mỗi lần. Chỉ kết hợp các tài liệu nếu bạn định sử dụng chúng cùng nhau.
- Cân nhắc việc sao chép dữ liệu vì dung lượng lưu trữ rẻ hơn so với sức mạnh máy tính hiện nay.
- Tối ưu hóa giản đồ cho các trường hợp sử dụng thường xuyên hơn.
- Mảng không được phát triển vượt quá giới hạn. Nếu có hơn vài trăm tài liệu con thì đừng nhúng tài liệu đó.
- Ưu tiên các phép nối cấp ứng dụng hơn các phép nối cấp cơ sở dữ liệu. Với việc lập chỉ mục thích hợp và sử dụng các trường chiếu hợp lý, nó có thể giúp bạn tiết kiệm rất nhiều thời gian.