diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2019-05-24 08:47:03 +1000 |
---|---|---|
committer | Luke Chen <luke.chen@mongodb.com> | 2019-07-12 11:56:17 +1000 |
commit | 98285cd9c36ac995a0207012c6742c2cefc03dd4 (patch) | |
tree | 93cb483d2e39001a4af348845a47d4cc74140d8a | |
parent | 203710762287e17248bf5851254725647bb3041e (diff) | |
download | mongo-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.cpp | 33 |
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); |