Tôi có bộ sưu tập MongoDB có tên post
với các đối tượng 35 triệu. Bộ sưu tập có hai chỉ mục phụ được định nghĩa như sau.Truy vấn phạm vi chậm trên chỉ mục nhiều mức
> db.post.getIndexKeys()
[
{
"_id" : 1
},
{
"namespace" : 1,
"domain" : 1,
"post_id" : 1
},
{
"namespace" : 1,
"post_time" : 1,
"tags" : 1 // this is an array field
}
]
tôi hy vọng các truy vấn sau đây, mà chỉ đơn giản lọc bởi namespace
và post_time
, để chạy trong một thời gian hợp lý mà không quét tất cả các đối tượng.
>db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).count()
7408
Tuy nhiên, phải mất MongoDB ít nhất mười phút để lấy kết quả và, một cách tò mò, nó quản lý để quét 70 triệu đối tượng để thực hiện công việc theo chức năng explain
.
> db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).explain()
{
"cursor" : "BtreeCursor namespace_1_post_time_1_tags_1",
"isMultiKey" : true,
"n" : 7408,
"nscannedObjects" : 69999186,
"nscanned" : 69999186,
"nscannedObjectsAllPlans" : 69999186,
"nscannedAllPlans" : 69999186,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 378967,
"nChunkSkips" : 0,
"millis" : 290048,
"indexBounds" : {
"namespace" : [
[
"my_namespace",
"my_namespace"
]
],
"post_time" : [
[
ISODate("2013-04-09T00:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
],
"tags" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "localhost:27017"
}
Sự khác biệt giữa số lượng đối tượng và số lần quét phải do độ dài của mảng thẻ (tất cả bằng 2). Tuy nhiên, tôi không hiểu tại sao bộ lọc post_time
không sử dụng chỉ mục.
Bạn có thể cho tôi biết những gì tôi có thể bị thiếu không?
(Tôi đang làm việc trên một máy gốc với 24 lõi và 96 GB RAM Tôi đang sử dụng MongoDB 2.2.3..)
Có không gian tên nào có số lượng cardinality rất thấp? – Sammaye
Hiện tại, chỉ có một giá trị 'không gian tên' riêng biệt, là giá trị tôi đang sử dụng. –
Đó là lý do tại sao, MongoDB phải giới hạn trên trường đầu tiên trước tiên, vì vậy nó nhận tất cả 'my_namespace' và sau đó nhận tất cả tài liệu giữa ngày đó, v.v., hãy thử sắp xếp lại chỉ mục để post_time là – Sammaye