Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Cách cải thiện hiệu suất truy vấn trường trong MongoDB

Giới thiệu

Để cải thiện hiệu suất truy vấn trên một trường, giải pháp chính là tạo **index (chỉ mục)** cho trường đó. Index cho phép MongoDB tìm tài liệu nhanh chóng mà không cần quét toàn bộ collection (collection scan).

Ví dụ minh họa

1. Tạo collection với dữ liệu lồng nhau

> db.caiThienTruyVan.insertOne({
    "ThongTinNguoiChoi": [
        { "TenNguoiChoi": "John", "DiemGame": 5690 },
        { "TenNguoiChoi": "Carol", "DiemGame": 2690 }
    ]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9dbaf875e2eeda1d5c3670") }

2. Tạo index trên nested field "ThongTinNguoiChoi.TenNguoiChoi"

> db.caiThienTruyVan.ensureIndex({ "ThongTinNguoiChoi.TenNguoiChoi": 1 });
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }

Lưu ý: ensureIndex() đã deprecated. Dùng createIndex():

db.caiThienTruyVan.createIndex({ "ThongTinNguoiChoi.TenNguoiChoi": 1 });

3. Truy vấn chính xác (Exact match)

> db.caiThienTruyVan.find({ "ThongTinNguoiChoi.TenNguoiChoi": "Carol" }).pretty();

4. Kết quả

{ "_id" : ObjectId("5c9dbaf875e2eeda1d5c3670"), "ThongTinNguoiChoi" : [ { "TenNguoiChoi" : "John", "DiemGame" : 5690 }, { "TenNguoiChoi" : "Carol", "DiemGame" : 2690 } ] }

Phân tích: Index có được dùng không?

Dùng explain("executionStats") để kiểm tra:

db.caiThienTruyVan.find({ "ThongTinNguoiChoi.TenNguoiChoi": "Carol" }).explain("executionStats")

Kết quả mong muốn: "stage" : "IXSCAN" (Index Scan) thay vì "stage" : "COLLSCAN" (Collection Scan).

Các loại index phổ biến

Loại IndexCú phápUse case
Single Field{ field: 1 }Truy vấn trên 1 trường
Compound{ field1: 1, field2: -1 }Truy vấn kết hợp nhiều trường
Multikey (Array)Tự động khi index field là arrayTruy vấn phần tử trong mảng
Text{ field: "text" }Full text search
Geospatial{ field: "2dsphere" }Truy vấn địa lý

Best Practices cho Index

  • Tạo index khớp với query pattern thực tế
  • Thứ tự field trong compound index quan trọng: Equality -> Sort -> Range
  • Tránh tạo quá nhiều index (tốn RAM, chậm write)
  • Dùng explain() để verify index được sử dụng
  • Monitor với db.currentOp() và db.serverStatus().metrics.queryExecutor.scanned

Cảnh báo về ví dụ gốc

Ví dụ gốc truy vấn "ThongTinNguoiChoi.TenNguoiChoi": "Carol" trên array sẽ trả về **cả document cha** (chứa cả John và Carol). Để chỉ lấy element Carol, dùng $elemMatch hoặc aggregation $unwind.