summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2019-05-24 08:47:03 +1000
committerLuke Chen <luke.chen@mongodb.com>2019-07-12 11:56:17 +1000
commit98285cd9c36ac995a0207012c6742c2cefc03dd4 (patch)
tree93cb483d2e39001a4af348845a47d4cc74140d8a
parent203710762287e17248bf5851254725647bb3041e (diff)
downloadmongo-98285cd9c36ac995a0207012c6742c2cefc03dd4.tar.gz
SERVER-41016 Calculate deltas for updates to large documents.
(cherry picked from commit 0d16c757b7badfcadac2a6794525f3c41a621a07)
-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 3fc1633b329..cdd9999a7c1 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -1377,8 +1377,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);