node.js - MongoDB 检查索引集合上的键太多

标签 node.js mongodb performance

我正在尝试从索引集合中获取一些记录,但太多 总是检查 key

这是我的查询

 db.getCollection('transactions').find({"vout.address" : { "$in":['LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd']} , _id: {$lt: '5e232dec225b5b1c61057ddb'}})
.limit(10).sort({blocknumber: -1 , _id: -1}).hint({ 'vout.address': -1, 'blocknumber': -1, '_id': -1 }).explain();

我的索引:

vout.address_-1_blocknumber_-1__id_-1

解释返回以下内容:

    { queryPlanner:
   { plannerVersion: 1,
     namespace: 'blockchain.ltc_transactionsTable',
     indexFilterSet: false,
     parsedQuery:
      { '$and':
         [ { 'vout.address': { '$eq': 'LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd' } },
           { _id:
              { '$lt':
                 ObjectID {
                   _bsontype: 'ObjectID',
                   id:
                    Buffer [Uint8Array] [ 94, 35, 45, 236, 34, 91, 91, 28, 97, 5, 125, 219 ] } } } ] },
     winningPlan:
      { stage: 'LIMIT',
        limitAmount: 10,
        inputStage:
         { stage: 'FETCH',
           inputStage:
            { stage: 'IXSCAN',
              keyPattern: { 'vout.address': -1, blocknumber: -1, _id: -1 },
              indexName: 'vout.address_-1_blocknumber_-1__id_-1',
              isMultiKey: true,
              multiKeyPaths: { 'vout.address': [ 'vout' ], blocknumber: [], _id: [] },
              isUnique: true,
              isSparse: false,
              isPartial: false,
              indexVersion: 2,
              direction: 'forward',
              indexBounds:
               { 'vout.address':
                  [ '["LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd", "LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd"]' ],
                 blocknumber: [ '[MaxKey, MinKey]' ],
                 _id:
                  [ '(ObjectId(\'5e232dec225b5b1c61057ddb\'), ObjectId(\'000000000000000000000000\')]' ] } } } },
     rejectedPlans: [] },
  executionStats:
   { executionSuccess: true,
     nReturned: 10,
     executionTimeMillis: 2,
     totalKeysExamined: 911,
     totalDocsExamined: 10,
     executionStages:
      { stage: 'LIMIT',
        nReturned: 10,
        executionTimeMillisEstimate: 0,
        works: 912,
        advanced: 10,
        needTime: 901,
        needYield: 0,
        saveState: 7,
        restoreState: 7,
        isEOF: 1,
        limitAmount: 10,
        inputStage:
         { stage: 'FETCH',
           nReturned: 10,
           executionTimeMillisEstimate: 0,
           works: 911,
           advanced: 10,
           needTime: 901,
           needYield: 0,
           saveState: 7,
           restoreState: 7,
           isEOF: 0,
           docsExamined: 10,
           alreadyHasObj: 0,
           inputStage:
            { stage: 'IXSCAN',
              nReturned: 10,
              executionTimeMillisEstimate: 0,
              works: 911,
              advanced: 10,
              needTime: 901,
              needYield: 0,
              saveState: 7,
              restoreState: 7,
              isEOF: 0,
              keyPattern: { 'vout.address': -1, blocknumber: -1, _id: -1 },
              indexName: 'vout.address_-1_blocknumber_-1__id_-1',
              isMultiKey: true,
              multiKeyPaths: { 'vout.address': [ 'vout' ], blocknumber: [], _id: [] },
              isUnique: true,
              isSparse: false,
              isPartial: false,
              indexVersion: 2,
              direction: 'forward',
              indexBounds:
               { 'vout.address':
                  [ '["LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd", "LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd"]' ],
                 blocknumber: [ '[MaxKey, MinKey]' ],
                 _id:
                  [ '(ObjectId(\'5e232dec225b5b1c61057ddb\'), ObjectId(\'000000000000000000000000\')]' ] },
              keysExamined: 911,
              seeks: 902,
              dupsTested: 10,
              dupsDropped: 0 } } },
     allPlansExecution: [] },
        keyId: Long { _bsontype: 'Long', low_: 1, high_: 1570062499 } } },
  operationTime:
   Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1579375735 } }

我预计它只检查 10 个键,但它正在检查 911 个键,我注意到 如果我通过不同的 _id 获取,则 totalKeysExamined 更改取决于 _id 位置(如果它来自) 最后插入的文档,数量较低,如果是来自第一个文档,则数量 很大

这是我数据库中的示例文档

{
    "_id" : ObjectId("5e206f6f47fafc6b7fa32d0a"),
    "txid" : "33deab70007a4210b2545f1ad516319bdedbcc836faf777c4af27431eab37c6d",
    "size" : 134,
    "vsize" : 134,
    "locktime" : 0,
    "weight" : null,
    "version" : 1,
    "vin" : [ 
        {
            "coinbase" : true
        }
    ],
    "vout" : [ 
        {
            "value" : 50,
            "n" : 0,
            "address" : "LMUZF47ySkrJ1njBRdQDyPVKkicziiZdQd",
            "spent" : false,
            "spent_ids" : []
        }
    ],
    "blocknumber" : 37,
    "time" : 1318474943
}

最佳答案

Mongo 的索引以 b-tree 形式构建,如 this 中所述。视频。

我们无法真正知道树是如何构建的,但索引查询不太可能只检查 x 所需的文档(因为这需要所有这些文档都位于上层树中)水平)。

您从未提到过您的集合的规模,但是检查 900 个索引(或者用技术术语来说,迭代估计的 200 个树 Node )似乎并不是不合理。

您对基于_id检查的文档的观察证实,一定范围会使树遍历更短,从而使mongo检查更少的文档。在一个非常简单的示例中,假设我们正在根据 _id 获取一个文档,如果文档 _id 在我们的 b-tree 根中建立了索引将检查单个文档,如果它位于其叶 Node 之一,我们将根据树的深度检查更多内容。

关于node.js - MongoDB 检查索引集合上的键太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59804120/

相关文章:

android - Flutter - initState() 中的复杂函数会降低导航和性能

javascript - React 有没有办法在不构建虚拟树的情况下更新 DOM?

node.js - 将nodejs永久安装/添加到(Jenkins)docker镜像中

arrays - nodejs从缓冲区数据到字节数组的转换

javascript - 我得到一个 fs.js :347 throw new TypeError ('Bad arguments' );

node.js - 从回调中捕获异常

mongodb:执行geoNear聚合时无法获取查询执行器

performance - 为什么 Julia 使用列专业?快吗

html - 如何在本地通过 Node.js 提供静态文件?

Node.js + MongoDB + Express + Mongoose 。如何通过简单的代码要求特定文件夹中的所有模型?