- vừa được xem lúc

MongoDB Views và Materialized Views: Khi nào nên sử dụng?

0 0 1

Người đăng: Vinh Phạm

Theo Viblo Asia

MongoDB cung cấp các công cụ mạnh mẽ để đơn giản hóa việc truy cập dữ liệu và cải thiện hiệu suất. Trong số đó có Standard Views và Materialized Views, hai cách tiếp cận cho phép bạn kiểm soát cách dữ liệu được đọc và trình bày, mỗi loại đều có những ưu nhược điểm và tình huống sử dụng riêng.

Trong bài viết này, chúng ta sẽ khám phá sự khác biệt giữa hai loại này và khi nào nên sử dụng từng loại một cách hiệu quả.

MongoDB Standard View là gì?

Bạn đang làm việc với MongoDB và nghe đến thứ gọi là “view”? Liệu chúng có giống nhau không? Không hẳn.

MongoDB Standard View (hay đơn giản là View) về cơ bản là một truy vấn đã được lưu sẵn (aggregation pipeline). Nó hoạt động như một bộ sưu tập ảo (virtual collection). Khi bạn truy vấn view này, MongoDB sẽ chạy truy vấn đã lưu trên các bộ sưu tập thực tại thời điểm đó.

  • Chỉ là logic: Không lưu dữ liệu, chỉ lưu định nghĩa truy vấn.
  • Chỉ đọc: Không thể ghi dữ liệu vào view.
  • Sử dụng aggregation pipeline để xác định nội dung hiển thị.
  • Chỉ là metadata: MongoDB chỉ lưu định nghĩa truy vấn, không lưu kết quả. Do đó không tốn thêm dung lượng lưu trữ.

Tóm lại, View giống như một lối tắt giúp bạn không phải viết đi viết lại truy vấn phức tạp mỗi lần.

Materialized View là gì?

Khác với Standard View, Materialized View thực sự lưu trữ dữ liệu. Nó là một bộ sưu tập thông thường chứa kết quả đã được tính toán trước từ một truy vấn aggregation.

Tuy nhiên, MongoDB không hỗ trợ natively (tính đến thời điểm hiện tại). Khi nói đến materialized view trong MongoDB, đó là một mô hình bạn tự triển khai, tức là tạo ra một bộ sưu tập khác chứa kết quả đã được tính toán sẵn.

  • Lưu trữ kết quả: Aggregation được chạy và kết quả được lưu vào một bộ sưu tập thực.
  • Đã tính toán sẵn: Không cần tính lại mỗi lần truy vấn.
  • Giả lập denormalization: Giống như tạo bảng chỉ chứa dữ liệu bạn cần cho các truy vấn nhanh.

Bạn sẽ đánh đổi giữa độ tươi mới của dữ liệu và tốc độ đọc, vì đọc từ collection đã được tính sẵn nhanh hơn rất nhiều so với việc tính toán lại mỗi lần.

So sánh: MongoDB Views vs Materialized Views

Độ tươi mới của dữ liệu

  • Views: Luôn luôn hiển thị dữ liệu mới nhất vì chạy truy vấn trực tiếp.
  • Materialized Views: Chỉ mới như lần cập nhật gần nhất. Nếu cập nhật 1 lần/ngày thì dữ liệu có thể cũ tới 24 giờ.

Hiệu suất

  • Views: Phụ thuộc vào độ phức tạp của truy vấn gốc. Aggregation nặng sẽ chậm.
  • Materialized Views: Đọc rất nhanh vì chỉ là đọc từ một collection đã tính sẵn. Nhưng ghi thì nặng vì phải chạy aggregation và ghi kết quả định kỳ.

Lưu trữ

  • Views: Gần như không tốn dung lượng, chỉ lưu truy vấn.
  • Materialized Views: Tốn dung lượng vì lưu dữ liệu kết quả (có thể bị trùng lặp).

Bảo trì

  • Views: Gần như không có. Định nghĩa một lần, dùng mãi.
  • Materialized Views: Bạn phải tự xây dựng và duy trì quá trình cập nhật, xử lý lỗi, thay đổi cấu trúc dữ liệu nguồn,...

Hỗ trợ trong MongoDB

  • Views: Được hỗ trợ hoàn toàn.
  • Materialized Views: Không được hỗ trợ trực tiếp. Bạn phải dùng aggregation ($out, $merge), scheduler hoặc Change Streams để tự xây dựng.

Bảo mật và trừu tượng hóa

  • Views: Tuyệt vời. Có thể cấp quyền đọc riêng cho từng view, ẩn bớt dữ liệu.
  • Materialized Views: Chỉ là một collection khác, cần cấp quyền như bình thường.

Khi nào nên dùng Views hoặc Materialized Views?

Khi nào nên dùng Views?

  • Ẩn logic phức tạp: Giúp dev truy vấn dễ dàng, ví dụ thay vì viết pipeline dài, chỉ cần gọi order_analytics_view.
  • Bảo mật dữ liệu: Tạo view chỉ hiển thị một số trường hoặc bản ghi cho người dùng/role cụ thể.
  • Prototyping nhanh: Định hình dữ liệu nhanh chóng mà không cần thay đổi collection gốc.
  • Dashboard nhẹ: Các dashboard cần dữ liệu thời gian thực, không aggregation nặng.

Khi nào nên dùng Materialized Views?

  • Dashboard hiệu suất cao: Các trang phân tích cần phản hồi nhanh, chạy lại cùng một truy vấn nặng nhiều lần.
  • Báo cáo nặng: Truy vấn aggregation phức tạp, dễ timeout. Chạy vào ban đêm, lưu kết quả để truy xuất nhanh.
  • Tổng hợp dữ liệu time-series: Ví dụ như tính trung bình tháng từ dữ liệu cảm biến hàng ngày.
  • Tối ưu cho microservice: Tạo collection riêng, dạng denormalized, phục vụ một microservice cụ thể.

Cách triển khai MongoDB View

Tạo View bằng MongoDB Shell

// Connect to your database first
// Example: use my_database db.createView( "active_users_view", // The name of your new view "users", // The source collection [ // The aggregation pipeline { $match: { status: "active" } } ] 

Sau đó bạn có thể truy vấn như collection thường:

db.active_users_view.find()

Tạo View bằng MongoDB Driver (Node.js)

const client = await MongoClient.connect(process.env.MONGODB_URI);
const db = client.db(process.env.DATABASE_NAME); await db.createCollection("active_users_view", { viewOn: "users", pipeline: [ { $match: { status: "active" } } ]
});

Cập nhật View

View không thể thay đổi trực tiếp. Bạn cần:

  • Xóa rồi tạo lại:
db.active_users_view.drop();
// Now create it again with the new definition db.createView("active_users_view", "users", [ /* new pipeline */ ]);
  • Versioning: Tạo view mới với version (vd: active_users_v2), cập nhật code dùng version mới.

Cách triển khai Materialized View

MongoDB không có câu lệnh CREATE MATERIALIZED VIEW. Bạn phải tự làm bằng aggregation.

Tạo/Làm mới bằng $out

db.orders.aggregate([ { $match: { status: "completed" } // Only completed orders }, { $group: { _id: "$customerId", // Group by customer totalSpent: { $sum: "$amount" } // Sum their order amounts } }, { $out: "customer_spending_mv" // Write results to this collection (materialized view) }
]);

Lưu ý: $out thay thế toàn bộ collection mỗi lần chạy. Nếu aggregation lỗi giữa chừng, collection có thể mất tạm thời.

Tạo/Làm mới bằng $merge

db.orders.aggregate([ { $match: { status: "completed" } // Only completed orders }, { $group: { _id: "$customerId", // Group by customer totalSpent: { $sum: "$amount" } // Sum their order amounts } }, { $merge: { into: "customer_spending_mv", // The target collection on: "_id", // Field to match documents on whenMatched: "replace", // What to do if a document matches (update it) whenNotMatched: "insert" // What to do if no document matches (insert it) } }
])

Tự xử lý hoàn toàn

Bạn có thể tự viết script truy vấn dữ liệu gốc rồi cập nhật collection đích. Linh hoạt nhất, nhưng tốn công nhất.

Chiến lược cập nhật: Làm mới theo yêu cầu vs. định kỳ

  • Làm mới theo yêu cầu: Khi cần thì cập nhật. Đơn giản nhưng dễ bị cũ.
  • Làm mới theo lịch (Batch): Dùng cron, hoặc MongoDB Atlas Trigger để cập nhật định kỳ.
  • Làm mới gần thời gian thực: Dùng Change Streams để theo dõi thay đổi và cập nhật từng phần. Cần replica set.

Tùy nhu cầu về độ tươi mới và tài nguyên mà chọn cách phù hợp.

Đo hiệu suất: Views vs Materialized Views

Mình tạo app Node.js để benchmark:

Chạy lần lượt:

npm run setup-db # setup the `sales` database
npm run seed-data # seed the `orders` collection
npm run create-standard-view # create the `order_analytics_view` view
npm run create-materialized-view # create the `order_analytics_materialized` materialized view
npm run start # run the Node.js server

Sau đó truy cập: http://localhost:3000/api/analytics/compare

Kết quả trong môi trường test:

"performance": { "standardView": { "queryTimeMs": 274, "resultCount": 100 }, "materializedView": { "queryTimeMs": 6, "resultCount": 100, "lastUpdated": "2025-04-20T06:19:40.416Z" }, "comparison": { "timeDifferenceMs": 268, "percentageDifference": "97.81%" } }

Materialized View nhanh hơn tới 97.81% – hoàn toàn dễ hiểu.

Tình huống sử dụng phù hợp

image.png

Kết luận

Chúng ta đã tìm hiểu:

  • Standard View là truy vấn được lưu sẵn.
  • Materialized View là dữ liệu đã được lưu sau khi tính toán.

Mỗi loại đều có điểm mạnh – điểm yếu:

  • Standard Views: Đơn giản, dữ liệu luôn mới, nhưng có thể chậm.
  • Materialized Views: Truy vấn nhanh, nhưng phức tạp, có thể bị cũ và tốn dung lượng.

Hãy chọn công cụ phù hợp với bài toán. Đừng “over-engineer” nếu chỉ cần View đơn giản, nhưng cũng đừng ngại dùng Materialized View nếu bạn cần tốc độ cao.

Và đừng quên – có thể kết hợp cả hai để tận dụng ưu điểm của từng loại.

Bình luận

Bài viết tương tự

- vừa được xem lúc

The Twelve-Factor App, cẩm nang gối đầu giường trong xây dựng application (Phần 1)

Giới thiệu. Ngày nay các phần mềm được triển khai dưới dạng các dịch vụ, chúng được gọi là các web apps hay software-as-a-service (SaaS).

0 0 39

- vừa được xem lúc

8 Sai lầm phổ biến khi lập trình Android

1. Hard code.

0 0 199

- vừa được xem lúc

Popular interview question: What is the difference between Process and Thread? 10 seconds a day

Video được đăng tại channel Tips Javascript

0 0 38

- vừa được xem lúc

Thuật toán và ứng dụng - P1

Mục đích series. . Những bài toán gắn liền với thực tế. Từ đó thấy được tầm quan trọng của thuật toán trong lập trình.

0 0 42

- vừa được xem lúc

Tác dụng của Docker trong quá trình học tập

Docker bây giờ gần như là kiến thức bắt buộc đối với các anh em Dev và Devops, nhưng mà đối với sinh viên IT nói chung vẫn còn khá mơ hồ và không biết tác dụng thực tế của nó. Hôm nay mình sẽ chia sẻ

0 0 47

- vừa được xem lúc

Làm giàu trong ngành IT

Hầu như mọi người đều đi làm để kiếm tiền, ít người đi làm vì thấy cái nghề đó thú vị lắm. Bây giờ vất cho mình 100 tỷ bảo mình bỏ nghề thì mình cũng bỏ thôi.

0 0 49