MongoDB-_id的Find()花费了很长时间-planSummary:IDHACK(timeAcquiringMicros等于查询时间)

时间:2019-10-04 14:01:43

标签: mongodb

我想知道为什么即使集合只有一个文档,下面的查询仍要花这么长时间(21秒)才能执行。我有一个具有130个数据库的副本集PSA实例,该集合在集合和索引之间共提供500K文件(350GB)。 Linux服务器具有32GB RAM和8个CPU,但是我们没有IO和CPU绑定。我正在将MongoDB 3.2与Wiredtiger引擎一起使用。

timeAcquiringMicros与查询时间之间有什么关系?

2019-10-03T11:30:34.249-0300I COMMAND[
   conn370659
]command bd01.000000000000000000000000 command:find{
   find:"000000000000000000000000",
   filter:{
      _id:ObjectId('000000000000000000000006')
   },
   batchSize:300
}planSummary:IDHACK
    keysExamined:1
    docsExamined:1
    idhack:1
    cursorExhausted:1
    keyUpdates:0
    writeConflicts:0
    numYields:0
    nreturned:1
    reslen:102226
locks:{
   Global:{
      acquireCount:{
         r:2
      }
   },
   Database:{
      acquireCount:{
         r:1
      },
      acquireWaitCount:{
         r:1
      },
      timeAcquiringMicros:{
        r:21893874
      }
   },
   Collection:{
      acquireCount:{
         r:1
      }
   }
}protocol:op_query 21894ms

1 个答案:

答案 0 :(得分:1)

MongoDB使用multiple granularity locking帮助改善并行性。有一些操作需要锁定在“全局”,“数据库”或“集合”级别。

您的查询中看到几个acquireCount: { r: X }r试图获得“意图共享锁”,这只是一种说法,我不需要将任何人都锁定在外,但是我想在达到所需级别之前,请获取每个级别的读取的松散锁定。这样可以防止您的查询在排他性写操作发生在您需要经历的任何级别时执行。

对您来说重要的是,您看到了:

   Database:{
      acquireCount:{
         r:1
      },
      acquireWaitCount:{
         r:1
      },
      timeAcquiringMicros:{
        r:21893874
      }

表示需要花费21893874毫秒来获取您在 Database 级别所需的锁。您的查询通过了Global级别,但是被在Dattabase级别具有排他锁的东西阻止了。我建议在MongoDB文档What locks are taken by some common client operations?中熟悉此表。

您所处情况的一种假设是有人决定在数据库的前台创建索引。这很有趣,因为您通常会在集合上创建索引,但是您需要在数据库上具有排他性的写锁定,以将您所有的集合锁定在该数据库中。

另一个假设是您的数据库正处于高负荷状态。您需要像Percona的MongoDB Prometheus Exporter这样的东西来从数据库中抓取数据,但是如果您能够以其他方式获取数据,那么这两篇博客文章可以帮助您了解性能瓶颈。

Percona Monitoring and Management (PMM) Graphs Explained: WiredTiger and Percona Memory Engine

Percona Monitoring and Management (PMM) Graphs Explained: MongoDB MMAPv1