MongoDB проверяет слишком много ключей в индексированной коллекции - PullRequest
1 голос
/ 18 января 2020

Я пытаюсь получить некоторые записи из индексированной коллекции, но всегда проверяется слишком много ключей

вот мой запрос

 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
}

1 Ответ

1 голос
/ 18 января 2020

Пн go индексы построены в виде b-tree, как объяснено в этом видео.

Мы не можем на самом деле знать, как было построено дерево, но Индексированные запросы очень маловероятны для проверки только x требуемых документов (поскольку для этого все эти документы должны находиться на верхних уровнях дерева).

Вы ни разу не упомянули масштаб своей коллекции, хотя изучали 900 индексы (или в технических терминах, повторяющих пару оценок 200 узлов дерева) не кажутся необоснованными.

Ваше наблюдение документов, проверенных на основе _id, подтверждает, что определенный диапазон сделает дерево ход короче, следовательно, заставьте mon go проверять меньше документов. В действительно упрощенном примере представьте, что мы выбираем один документ на основе _id, если документы _id проиндексированы в b-tree root, мы бы проверили один документ, и если его в одном из его конечных узлов мы будет проверять больше в зависимости от глубины деревьев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...