summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2019-05-24 08:47:03 +1000
committerEric Milkie <milkie@10gen.com>2019-07-31 09:13:09 -0400
commite01b2ea5d1ecb076159a2e260524c2a2e381d36d (patch)
tree02f56963bb5bdaaa6eab69003c126f56146c7bc2
parenteffa12b407861d211fd706992d92e6d39b24e493 (diff)
downloadmongo-e01b2ea5d1ecb076159a2e260524c2a2e381d36d.tar.gz
SERVER-41016 Calculate deltas for updates to large documents.
(cherry picked from commit 0d16c757b7badfcadac2a6794525f3c41a621a07) (cherry picked from commit 98285cd9c36ac995a0207012c6742c2cefc03dd4)
-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 99183a6fb6f..92957b49c45 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp
@@ -1270,8 +1270,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);