summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Williams <louis.williams@mongodb.com>2021-06-01 13:37:26 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-06-15 15:26:51 +0000
commit297e2977ef3e394e02d61aedc954c9aaadc37e73 (patch)
treeb91a88ca2d9fc13309a7040346b0370b614fb441
parentcc7ffaa7a7e7462037a40fffa833987e7aa644c5 (diff)
downloadmongo-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.js17
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp13
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();