summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2019-05-24 08:47:03 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2019-05-24 08:47:03 +1000
commit0d16c757b7badfcadac2a6794525f3c41a621a07 (patch)
tree818dd566f93805cda36f0740801e255aa6f31974
parent0b39364ee1e923fd3e4e66f0e0bb0e57ca0deacd (diff)
downloadmongo-0d16c757b7badfcadac2a6794525f3c41a621a07.tar.gz
SERVER-41016 Calculate deltas for updates to large documents.
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp33
1 files changed, 31 insertions, 2 deletions
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
index 3fbe0726632..5bab4a26b67 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -1401,8 +1401,37 @@ Status WiredTigerRecordStore::updateRecord(OperationContext* opCtx,
}
WiredTigerItem value(data, len);
- c->set_value(c, value.Get());
- ret = WT_OP_CHECK(c->insert(c));
+
+ // Check if we should modify rather than doing a full update. Look for deltas for documents
+ // larger than 1KB, up to 16 changes representing up to 10% of the data.
+ const int kMinLengthForDiff = 1024;
+ const int kMaxEntries = 16;
+ const int kMaxDiffBytes = len / 10;
+
+ bool skip_update = false;
+ if (len > kMinLengthForDiff && len <= old_length + kMaxDiffBytes) {
+ int nentries = kMaxEntries;
+ std::vector<WT_MODIFY> entries(nentries);
+
+ if ((ret = wiredtiger_calc_modify(
+ c->session, &old_value, value.Get(), kMaxDiffBytes, entries.data(), &nentries)) ==
+ 0) {
+ invariantWTOK(WT_OP_CHECK(nentries == 0 ? c->reserve(c)
+ : c->modify(c, entries.data(), nentries)));
+ WT_ITEM new_value;
+ dassert(nentries == 0 ||
+ (c->get_value(c, &new_value) == 0 && new_value.size == value.size &&
+ memcmp(data, new_value.data, len) == 0));
+ skip_update = true;
+ } else if (ret != WT_NOTFOUND) {
+ invariantWTOK(ret);
+ }
+ }
+
+ if (!skip_update) {
+ c->set_value(c, value.Get());
+ ret = WT_OP_CHECK(c->insert(c));
+ }
invariantWTOK(ret);
_increaseDataSize(opCtx, len - old_length);