diff options
author | Michael Cahill <michael.cahill@mongodb.com> | 2019-05-24 08:47:03 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2019-05-24 08:47:03 +1000 |
commit | 0d16c757b7badfcadac2a6794525f3c41a621a07 (patch) | |
tree | 818dd566f93805cda36f0740801e255aa6f31974 | |
parent | 0b39364ee1e923fd3e4e66f0e0bb0e57ca0deacd (diff) | |
download | mongo-0d16c757b7badfcadac2a6794525f3c41a621a07.tar.gz |
SERVER-41016 Calculate deltas for updates to large documents.
-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 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); |