Hướng dẫn set index in mongodb - đặt chỉ mục trong mongodb

Giới thiệu về Index

Index trong database cũng giống như mục lục của một cuốn sách. Thay vì tìm từng trang của cuốn sách Database tạo một mục lục, và nó chỉ việc tìm nội dung của cuốn sách qua mục lục đó. Qua đó giúp cho câu lệnh truy vấn nhanh hơn. Một câu truy vấn không có index được gọi là table scan. Nghĩa là Database phải xem qua toàn bộ các Document để tìm được kết quả truy vấn, và đối với các collection lớn, câu truy vấn sẽ rất chậm. Để có ví dụ cụ thể, bạn có thể test thử như sau:table scan. Nghĩa là Database phải xem qua toàn bộ các Document để tìm được kết quả truy vấn, và đối với các collection lớn, câu truy vấn sẽ rất chậm. Để có ví dụ cụ thể, bạn có thể test thử như sau:

    use test     // chúng ta dùng database test để thử.
    for[var i = 0; i  0x0c965148
    "user101" => 0xf51f818e
    "user102" => 0x00fd7934
    ...
}

Mỗi Index lấy giá trị của username là khóa và chứa giá trị là địa chỉ vật lý của thông tin Document lưu trên ổ đĩa. Ví dụ khi truy vấn là tìm

db.users.find[{username: 'user112'}].explain["executionStats"]["executionStats"]
{
	"executionSuccess" : true,
	"nReturned" : 1,
	"executionTimeMillis" : 269,
	"totalKeysExamined" : 0,
	"totalDocsExamined" : 1000000,
	"executionStages" : {
		"stage" : "COLLSCAN",
		"filter" : {
			"username" : {
				"$eq" : "user112"
			}
		},
		"nReturned" : 1,
		"executionTimeMillisEstimate" : 211,
		"works" : 1000002,
		"advanced" : 1,
		"needTime" : 1000000,
		"needYield" : 0,
		"saveState" : 7813,
		"restoreState" : 7813,
		"isEOF" : 1,
		"invalidates" : 0,
		"direction" : "forward",
		"docsExamined" : 1000000
	}
}
1, MongoDB sẽ gọi INDEXES['user100'] và lấy ra địa chỉ trỏ đến Document từ đó có thông tin của Document và trả về.

Sử dụng Compound Index

Loại Index mình sử dụng ở trên gọi là Single Field Index. Mình sẽ giới thiệu tiếp về Compound Index, với loại index này là bạn có thể đánh index cho 2 hay nhiều trường cùng một lúc. Đối với các câu truy vấn có nhiều điều kiện thì chỉ đánh index cho 1 trường là không đủ. Ví dụ mình có 1 triệu người dùng, một nửa là nam và một nửa là nữ. Số user này nằm trong độ tuổi 20-29, vậy mỗi độ tuổi sẽ có 100k người dùng. Giờ mình muốn query tất cả các user nữ 20 tuổi. trước tiên mình đánh index cho trường

db.users.find[{username: 'user112'}].explain["executionStats"]["executionStats"]
{
	"executionSuccess" : true,
	"nReturned" : 1,
	"executionTimeMillis" : 269,
	"totalKeysExamined" : 0,
	"totalDocsExamined" : 1000000,
	"executionStages" : {
		"stage" : "COLLSCAN",
		"filter" : {
			"username" : {
				"$eq" : "user112"
			}
		},
		"nReturned" : 1,
		"executionTimeMillisEstimate" : 211,
		"works" : 1000002,
		"advanced" : 1,
		"needTime" : 1000000,
		"needYield" : 0,
		"saveState" : 7813,
		"restoreState" : 7813,
		"isEOF" : 1,
		"invalidates" : 0,
		"direction" : "forward",
		"docsExamined" : 1000000
	}
}
2 trong bảng.

db.users.createIndex[{gender: 1}];
db.users.find[{gender: 'female', age: 29}];

Câu truy vấn trên sẽ lấy ngay ra được 500 nghìn users nữ, tuy nhiên ta vẫn sẽ phải duyệt qua 500 nghìn users này để tìm các users có tuổi là 29. Tiếp theo mình sẽ xóa index đã đánh, và đánh lại index cho trường age.

db.users.dropIndex[{gender: 1}];
db.users.createIndex[{age: 1}];
db.users.find[{gender: 'female', age: 29}];

Lần này thì DB sẽ chỉ phải duyệt qua 100 nghìn users để tìm các users có giới tính nữ. Bạn có thể thấy khi đánh Index ta nên chọn các trường có tính duy nhất lớn hơn để đánh Index. Tuy nhiên ta vẫn có thể đánh index cho cả 2 trường cùng 1 lúc.

db.users.createIndex[{age: 1, gender: 1}];
db.users.find[{gender: 'female', age: 29}];

Với cách này DB sẽ lấy ra ngay lập tức 50 nghìn users tương ứng. Vậy là với các câu lệnh truy vấn phức tạp hơn bạn có thể nghiên cứu để đánh Index cho các trường sao cho hiệu quả hơn.

Tổng kết

Qua bài viết của mình hy vọng các bạn có thể hiểu thêm về đánh Index, không chỉ với MongoDB mà còn cả với các hệ quản trị CSDL khác. Nếu có gì sai sót, mọi người có thể góp ý thêm cho mình, xin cảm ơn.

Bài Viết Liên Quan

Chủ Đề