diff --git a/src/mongo/db/index/bulk_builder_common.h b/src/mongo/db/index/bulk_builder_common.h index 0ae2a5c5b16..bad96f7de6e 100644 --- a/src/mongo/db/index/bulk_builder_common.h +++ b/src/mongo/db/index/bulk_builder_common.h @@ -97,6 +97,42 @@ public: } // namespace mongo int64_t iterations = 0; + std::vectornext())>> batch; + static constexpr auto kBatchSize = 1000; + batch.reserve(kBatchSize); + + auto insertBatch = [&](const auto& batch) -> Status { + try { + writeConflictRetry(opCtx, "addingKey", this->_ns, [&] { + WriteUnitOfWork wunit(opCtx); + for (const auto& [_, data] : batch) { + static_cast(this)->insertKey(builder, data); + } + wunit.commit(); + }); + } catch (DBException& e) { + Status status = e.toStatus(); + // Duplicates are checked before inserting. + invariant(status.code() != ErrorCodes::DuplicateKey); + return status; + } + + for (const auto& [isDup, data] : batch) { + Status status = + static_cast(this)->keyCommitted(onDuplicateKeyInserted, data, isDup); + if (!status.isOK()) + return status; + } + + { + stdx::unique_lock lk(*opCtx->getClient()); + // If we're here either it's a dup and we're cool with it or the addKey went + // just fine. + pm.get(lk)->hit(batch.size()); + } + return Status::OK(); + }; + while (it->more()) { opCtx->checkForInterrupt(); @@ -141,36 +177,24 @@ public: continue; } + batch.emplace_back(isDup, std::move(data)); - try { - writeConflictRetry(opCtx, "addingKey", _ns, [&] { - WriteUnitOfWork wunit(opCtx); - static_cast(this)->insertKey(builder, data); - wunit.commit(); - }); - } catch (DBException& e) { - Status status = e.toStatus(); - // Duplicates are checked before inserting. - invariant(status.code() != ErrorCodes::DuplicateKey); - return status; + if (batch.size() >= kBatchSize) { + Status status = insertBatch(batch); + if (!status.isOK()) { + return status; + } + batch.clear(); } - - Status status = - static_cast(this)->keyCommitted(onDuplicateKeyInserted, data, isDup); - if (!status.isOK()) - return status; - // Yield locks every 'yieldIterations' key insertions. if (yieldIterations > 0 && (++iterations % yieldIterations == 0)) { entry = yield(opCtx, collection, _ns, entry); } + } - { - stdx::unique_lock lk(*opCtx->getClient()); - // If we're here either it's a dup and we're cool with it or the addKey went just - // fine. - pm.get(lk)->hit(); - } + Status status = insertBatch(batch); + if (!status.isOK()) { + return status; } {