diff options
author | Louis Williams <louis.williams@mongodb.com> | 2021-06-01 13:37:26 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-15 15:26:51 +0000 |
commit | 297e2977ef3e394e02d61aedc954c9aaadc37e73 (patch) | |
tree | b91a88ca2d9fc13309a7040346b0370b614fb441 | |
parent | cc7ffaa7a7e7462037a40fffa833987e7aa644c5 (diff) | |
download | mongo-297e2977ef3e394e02d61aedc954c9aaadc37e73.tar.gz |
SERVER-56509 Wrap unique index insertion _keyExists call in a WT cursor reconfigure
This improves, but does not entirely fix a performance regression with
inserts and updates on unique indexes
(cherry picked from commit c5ac2eb1ea145693e1c6b974e88a2cfc18780134)
-rw-r--r-- | jstests/noPassthrough/profile_operation_metrics.js | 17 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp | 13 |
2 files changed, 17 insertions, 13 deletions
diff --git a/jstests/noPassthrough/profile_operation_metrics.js b/jstests/noPassthrough/profile_operation_metrics.js index 83a030af2f3..39427500a6d 100644 --- a/jstests/noPassthrough/profile_operation_metrics.js +++ b/jstests/noPassthrough/profile_operation_metrics.js @@ -694,9 +694,8 @@ const operations = [ // Insert should not perform any reads. assert.eq(profileDoc.docBytesRead, 0); assert.eq(profileDoc.docUnitsRead, 0); - // Reads the index entry for 'a' to determine uniqueness. - assert.eq(profileDoc.idxEntryBytesRead, 6); - assert.eq(profileDoc.idxEntryUnitsRead, 1); + assert.eq(profileDoc.idxEntryBytesRead, 0); + assert.eq(profileDoc.idxEntryUnitsRead, 0); assert.eq(profileDoc.cursorSeeks, 1); assert.eq(profileDoc.docBytesWritten, 29); assert.eq(profileDoc.docUnitsWritten, 1); @@ -762,9 +761,9 @@ const operations = [ assert.gte(profileDoc.docUnitsRead, 1); assert.gte(profileDoc.cursorSeeks, 4); } - // Reads index entries on '_id' for the lookup and 'a' to ensure uniqueness. - assert.eq(profileDoc.idxEntryBytesRead, 9); - assert.eq(profileDoc.idxEntryUnitsRead, 2); + // Reads index entries on '_id' for the lookup. + assert.eq(profileDoc.idxEntryBytesRead, 3); + assert.eq(profileDoc.idxEntryUnitsRead, 1); // This out-of-place update should perform a direct insert because it is not large // enough to qualify for the in-place update path. assert.eq(profileDoc.docBytesWritten, 29); @@ -802,9 +801,9 @@ const operations = [ assert.gte(profileDoc.docUnitsRead, 9); assert.gte(profileDoc.cursorSeeks, 4); } - // Reads index entries on '_id' for the lookup and 'a' to ensure uniqueness. - assert.eq(profileDoc.idxEntryBytesRead, 10); - assert.eq(profileDoc.idxEntryUnitsRead, 2); + // Reads index entries on '_id'. + assert.eq(profileDoc.idxEntryBytesRead, 4); + assert.eq(profileDoc.idxEntryUnitsRead, 1); if (FixtureHelpers.isReplSet(db)) { // When WT_MODIFY is used on a replicated collection fewer bytes are written per the // comment about WT_MODIFY above. diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index 690fbc0d0d8..01a7d64f72f 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -1408,13 +1408,13 @@ bool WiredTigerIndexUnique::_keyExists(OperationContext* opCtx, int cmp; int ret = wiredTigerPrepareConflictRetry(opCtx, [&] { return c->search_near(c, &cmp); }); + auto& metricsCollector = ResourceConsumption::MetricsCollector::get(opCtx); + metricsCollector.incrementOneCursorSeek(); + if (ret == WT_NOTFOUND) return false; invariantWTOK(ret); - auto& metricsCollector = ResourceConsumption::MetricsCollector::get(opCtx); - metricsCollector.incrementOneCursorSeek(); - if (cmp == 0) return true; @@ -1565,7 +1565,12 @@ Status WiredTigerIndexUnique::_insert(OperationContext* opCtx, invariantWTOK(ret); // Second phase looks up for existence of key to avoid insertion of duplicate key - if (_keyExists(opCtx, c, keyString.getBuffer(), sizeWithoutRecordId)) { + // The usage of 'prefix_key=true' enables an optimization that allows this search to return + // more quickly. See SERVER-56509. + c->reconfigure(c, "prefix_key=true"); + ON_BLOCK_EXIT([c] { c->reconfigure(c, "prefix_key=false"); }); + auto keyExists = _keyExists(opCtx, c, keyString.getBuffer(), sizeWithoutRecordId); + if (keyExists) { auto key = KeyString::toBson( keyString.getBuffer(), sizeWithoutRecordId, _ordering, keyString.getTypeBits()); auto entry = _desc->getEntry(); |