2013-05-09 36 views
6

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 namespacepost_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..)

+0

Có không gian tên nào có số lượng cardinality rất thấp? – Sammaye

+0

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. –

+0

Đó 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

Trả lời

3

Tìm thấy câu trả lời của tôi trong câu hỏi này: Order of $lt and $gt in MongoDB range query

chỉ số của tôi là một multikey chỉ mục (trên tags) và tôi đang chạy một truy vấn phạm vi (trên post_time). Apparently, MongoDB không thể sử dụng cả hai mặt của phạm vi làm bộ lọc trong trường hợp này, do đó, nó chỉ chọn mệnh đề $gte, xuất hiện trước. Khi giới hạn dưới của tôi xảy ra là giá trị post_time thấp nhất, MongoDB bắt đầu quét tất cả các đối tượng.

Thật không may, đây không phải là toàn bộ câu chuyện. Cố gắng giải quyết vấn đề, tôi cũng đã tạo ra các chỉ mục không phải đa nhân nhưng MongoDB đã khăng khăng sử dụng cái xấu. Điều đó khiến tôi nghĩ rằng vấn đề là ở nơi khác. Cuối cùng, tôi đã phải bỏ chỉ mục đa chỉ số và tạo một chỉ mục không có trường tags. Tất cả mọi thứ là tốt bây giờ.

+0

Dang Tôi không bao giờ biết rằng về '$ gt' và' $ lt' và miltikeys, rất hay! – Sammaye

+0

Sử dụng cursor.hint cũng có thể là giải pháp để làm cho mongodb sử dụng chỉ mục khác (http://docs.mongodb.org/manual/reference/method/cursor.hint/#cursor.hint) – rudi

Các vấn đề liên quan