2016-03-24 75 views
1

我有一個mondoDB集合,如下所示其中包含將近一百萬條目:MongoDB中發現慢於子陣查詢

{ 
_id: 'object id', 
link: 'a url', 
channels: [ array of ids ] 
pubDate: Date 
} 

我有相當頻繁地執行以下查詢:

db.articles.find({ $and: [ { pubDate: { $gte: new Date(<some date>) } }, { channels: ObjectId(<some object id>) } ] }) 

查詢即使我有一定的索引,速度也非常緩慢。最近,我跑在上面的解釋,這裏是結果:

{ 
    "cursor" : "BtreeCursor pubDate_-1_channels_1", 
    "isMultiKey" : true, 
    "n" : 2926, 
    "nscannedObjects" : 4245, 
    "nscanned" : 52611, 
    "nscannedObjectsAllPlans" : 8125, 
    "nscannedAllPlans" : 56491, 
    "scanAndOrder" : false, 
    "indexOnly" : false, 
    "nYields" : 5, 
    "nChunkSkips" : 0, 
    "millis" : 5378, 
    "indexBounds" : { 
     "pubDate" : [ 
      [ 
       ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ"), 
       ISODate("2016-03-04T21:00:00Z") 
      ] 
     ], 
     "channels" : [ 
      [ 
       ObjectId("54239b9477456cf777dd0d31"), 
       ObjectId("54239b9477456cf777dd0d31") 
      ] 
     ] 
    } 
} 

看起來像它使用的是正確的索引,但仍採取5秒以上運行。

我失去了一些東西在這裏?我的索引有問題嗎?

這裏是收集者均基於索引:

[ 
    { 
     "v" : 1, 
     "name" : "_id_", 
     "key" : { 
      "_id" : 1 
     }, 
     "ns" : "dbname.articles" 
    }, 
    { 
     "v" : 1, 
     "name" : "pubDate_-1_channels_1", 
     "key" : { 
      "pubDate" : -1, 
      "channels" : 1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    }, 
    { 
     "v" : 1, 
     "name" : "pubDate_-1", 
     "key" : { 
      "pubDate" : -1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    }, 
    { 
     "v" : 1, 
     "name" : "link_1", 
     "key" : { 
      "link" : 1 
     }, 
     "ns" : "dbname.articles", 
     "background" : true 
    } 
] 

這是我看到的時候我在收集運行數據:

{ 
    "ns" : "dbname.articles", 
    "count" : 2402741, 
    "size" : 2838416144, 
    "avgObjSize" : 1181.3242226274076, 
    "storageSize" : 3311443968, 
    "numExtents" : 21, 
    "nindexes" : 4, 
    "lastExtentSize" : 862072832, 
    "paddingFactor" : 1.000000000020535, 
    "systemFlags" : 0, 
    "userFlags" : 0, 
    "totalIndexSize" : 775150208, 
    "indexSizes" : { 
     "_id_" : 100834608, 
     "pubDate_-1_channels_1" : 180812240, 
     "pubDate_-1" : 96378688, 
     "link_1" : 397124672 
    }, 
    "ok" : 1 
} 
+0

您的索引策略看起來不錯。請注意,當所有文檔無法放入內存時,MongoDB開始變慢,而當所有索引字段無法放入內存時非常慢。你能編輯這個問題並添加[db.my_collection.stats()](https://docs.mongodb.org/manual/reference/method/db.collection.stats/)的結果並告訴我們有多少GB你在你的電腦上有RAM嗎? – CydrickT

+0

謝謝@CydrickT我添加了統計數據。該機器有1.5GB的Ram,這是一個小的EC2實例。我想這可能是內存問題。 – aqqush

+0

我添加了一個完整的答案@aqqush。如果有任何混淆,請不要猶豫,寫評論。 – CydrickT

回答

0

因此,根據db.my_collection.stats(),索引字段需要0.77gb("totalIndexSize" : 775150208字節),並且您的收集需要3.31gb("storageSize" : 3311443968字節)。你提到你的實例使用了1.5GB的RAM。

因此,MongoDB可以將所有索引保留在內存中,但沒有足夠的內存來保存所有文檔。所以,當它需要對未加載到內存中的文檔執行查詢時,速度會變慢。我敢打賭,如果你兩次運行相同的查詢,它將花費更少的時間,因爲必要的文檔已經被加載到內存中。

我會建議嘗試與5GB的RAM。做幾個查詢,以便將所有文檔加載到內存中,然後比較速度。

0

您的索引{發佈時間:-1,通道:1}對我來說很不錯。

雖然我會嘗試{channel:1,pubDate:-1}

此建議的原因如下:

請注意,索引有順序。 您正在使用的索引是pubDate_-1_channels_1,這與索引channels_1_pubDate_-1(按相反順序)不同。

根據您擁有的頻道數量,我會期望對於您的查詢,一個索引應該比另一個索引效率更高。

有關詳細信息,請參閱prefixes上的手冊。