2013-05-09 41 views
6

post adında bir MongoDB koleksiyonum var 35 milyon nesneler. Koleksiyonda aşağıdaki şekilde tanımlanan iki ikincil dizin bulunur.Çok değişkenli bir dizinde yavaş aralıklı sorgu

> db.post.getIndexKeys() 
[ 
    { 
     "_id" : 1 
    }, 
    { 
     "namespace" : 1, 
     "domain" : 1, 
     "post_id" : 1 
    }, 
    { 
     "namespace" : 1, 
     "post_time" : 1, 
     "tags" : 1 // this is an array field 
    } 
] 

ben sadece namespace ve post_time filtreleyen aşağıdaki sorgu, tüm nesneleri tarayarak olmadan makul bir süre içinde çalıştırmak için bekliyoruz.

>db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).count() 
7408 

Ancak merakla, bu explain işleve göre iş yapmak 70 milyon nesneleri taramak için yönetir, sonuç almak için mongodb en az on dakika sürer ve.

> 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" 
} 

nesne sayısı ve tarama sayısı arasındaki fark

(bütün 2'ye eşit olan) etiket dizileri uzunlukta neden olmalıdır. Yine de, neden post_time filtresinin endeksten kullanıldığını anlamıyorum.

Neyi kaçırdığımı söyleyebilir misiniz?

(. Ben 24 çekirdek ve 96 GB RAM ben MongoDB 2.2.3 kullanıyorum bir iniş makinede çalışıyorum.)

+0

İsim adının çok düşük bir özelliği var mı? – Sammaye

+0

Şu an kullandığım tek bir "namespace" değeri var. –

+0

Bu nedenle, MongoDB ilk alanı ilk sınırlamak zorundadır, bu yüzden tüm "my_namespace" alır ve daha sonra tüm docs bu tarih, vb arasında alır, post_time önce dizinin yeniden düzenlenmesi deneyin – Sammaye

cevap

3

bu soruya benim cevap Bulunan: Order of $lt and $gt in MongoDB range query

Benim endeksi multikey olduğunu dizini (tags üzerinde) ve bir aralık sorgusu çalıştırıyorum (post_time üzerinde). Apparently, MongoDB, bu durumda bir filtre olarak aralığın her iki tarafını kullanamaz, bu yüzden önce gelen $gte maddesini seçer. Alt limitimin en düşük post_time değeri olması nedeniyle MongoDB tüm nesneleri taramaya başlar.

Maalesef, bu tüm hikaye değil. Sorunu çözmeye çalışırken, çok-olmayan indeksleri de yarattım ama MongoDB kötü olanı kullanmakta ısrar etti. Bu bana sorunun başka yer olduğunu düşünmemi sağladı. Son olarak, multikey indeksini düşürmek ve tags alanı olmadan bir tane oluşturmak zorunda kaldım. Şimdi her şey yolunda.

+0

Dang Bunu '$ gt' ve' $ lt' ve miltikeys, güzel bulmak hakkında hiç bilmiyordum! – Sammaye

+0

cursor.hint kullanımı da mongodb diğer dizini kullanmak için bir çözüm olabilir (http://docs.mongodb.org/manual/reference/method/cursor.hint/#cursor.hint) – rudi