2014-03-25 175 views
4

我的mongodb非常简单:数据集/条目在3层上有大约30个属性。一个这样的条目有大约5000个字符。我有500k。 当我执行以下查询......Mongodb查询异常缓慢

db.images.find({ "featureData.cedd": { $exists: false}}).count() 

...它是极其缓慢。它没有编入索引,但仍然...从我的MySQL经验来看,它不应该用20分钟执行一个这样的查询。

在执行时(直接在mongo终端上),CPU使用率为3%,仍然超过2G的可用内存。

谢谢你给我提示我可以做什么!

编辑:查询的解释()(不计数)给出:iostat的的

db.images.find({ "featureData.cedd": { $exists: false }}).explain() 
{ 
    "cursor" : "BasicCursor", 
    "nscanned" : 532537, 
    "nscannedObjects" : 532537, 
    "n" : 438, 
    "millis" : 1170403, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 

    } 
} 

输出:解释()

Linux 3.2.0-58-generic (campartex)  03/25/2014  _x86_64_  (2 CPU) 

avg-cpu: %user %nice %system %iowait %steal %idle 
      34.93 0.01 0.25 0.48 0.00 64.33 

Device:   tps kB_read/s kB_wrtn/s kB_read kB_wrtn 
sda    2.08  103.79  11.26 172805914 18749067 
fd0    0.00   0.00   0.00  148   0 

输出添加索引后:

db.images.find({ "featureData.cedd": { $exists: false }}).explain() 
{ 
    "cursor" : "BtreeCursor featureData.cedd_1", 
    "nscanned" : 438, 
    "nscannedObjects" : 438, 
    "n" : 438, 
    "millis" : 2, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : true, 
    "indexOnly" : false, 
    "indexBounds" : { 
      "featureData.cedd" : [ 
        [ 
          null, 
          null 
        ] 
      ] 
    } 
} 
+1

'解释查询总是一个好的第一步 – shx2

+0

顺便说一句,在编写诸如“计数mongo必须通过所有字符”之类的东西之前,请考虑一下,我们在这里谈论15分钟只有50万条记录。 。:) – Doidel

+0

我只能找到一个“解释()”,没有描述。并且“解释”现在运行1分钟x/CPU和内存使用率相同低 – Doidel

回答

0

在我的情况下,添加一个索引将查询速度提高了600'000倍。$exists:false寻找空值 - 只有在其他对象经常(如有效值)没有cedd:null时才有效。这是这种情况。此外,没有cedd值的对象要小得多。

5

TL; DR:反向逻辑:在新的fie上添加一个稀疏索引ld has_cedd或者是null或者是一些常量(低选择性指数,不理想,但是通过稀疏改进),或者更好的办法是在每个写操作更新的地方保存一个全局计数器。

索引featureData.cedd听起来像一个坏主意,如果它可以包含高达5k字符,因为这远远超出了最大索引大小,显然你对数据本身不感兴趣,只是它是否存在。

哦,为什么这会很慢?可能会快速保持临时请求。 MongoDB可以将所有资源分配给类似OLAP的查询,但是这会对任何“常规OLTP式查询”造成滞后。


这里有两个问题:

  1. $exists : false是邪恶的,我怀疑索引会有所帮助:索引对于数据制成,而$exists是一个“元查询”上结构体。如果字段上有一个索引并且查询为$exists : true,则它可以使用索引,因为如果索引值存在,则该字段本身也必须存在于给定文档中。反转该逻辑非常棘手:如果该字段不存在,则不在索引中,或者它具有超低的选择性。 “转向”索引通常是有问题的,对于顺便使用$ne的查询也是如此。

  2. MongoDB将不得不反序列化500k对象并检查每个对象以执行$exists。您无法将此与MySQL中的固定表结构进行比较,实际上,$exists : false没有与SQL等效的字段,因为该字段必须存在,否则您的表会严重损坏。

+0

感谢解释!仍然我想知道为什么只有3%的CPU用于OLAP查询?我能以某种方式增加吗?由于没有其他任何运行在数据库上,这将是相当浪费资源... – Doidel

+0

MAYDAY添加索引从20分钟到2毫秒! WTF!我添加了新的explain()作为对 – Doidel

+0

这个问题的编辑 Sooo我猜索引创建了一个没有这个特性的索引列表,因此搜索只需要扫描确切数量的结果,438在这种情况下? – Doidel