Skip to content

Commit 7db3428

Browse files
committed
Remove KVPair
1 parent e8c34ce commit 7db3428

7 files changed

Lines changed: 102 additions & 67 deletions

File tree

src/mongo/db/exec/idhack.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ PlanStage::StageState IDHackStage::doWork(WorkingSetID* out) {
120120
WorkingSetID id = WorkingSet::INVALID_ID;
121121
try {
122122
// Look up the key by going directly to the index.
123-
RecordId recordId = _accessMethod->findSingle(getOpCtx(), _key);
123+
RecordData recordData;
124+
RecordId recordId = _accessMethod->findSingle(getOpCtx(), _key, &recordData);
124125

125126
// Key not found.
126127
if (recordId.isNull()) {
@@ -135,7 +136,10 @@ PlanStage::StageState IDHackStage::doWork(WorkingSetID* out) {
135136
id = _workingSet->allocate();
136137
WorkingSetMember* member = _workingSet->get(id);
137138
member->recordId = recordId;
138-
_workingSet->transitionToRecordIdAndIdx(id);
139+
member->obj = {getOpCtx()->recoveryUnit()->getSnapshotId(), recordData.releaseToBson()};
140+
// _workingSet->transitionToRecordIdAndIdx(id);
141+
_workingSet->transitionToRecordIdAndObj(id);
142+
return advance(id, member, out);
139143

140144
if (!_recordCursor)
141145
_recordCursor = _collection->getCursor(getOpCtx());

src/mongo/db/exec/index_scan.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,12 @@ PlanStage::StageState IndexScan::doWork(WorkingSetID* out) {
224224
WorkingSetMember* member = _workingSet->get(id);
225225
member->recordId = kv->loc;
226226
member->keyData.push_back(IndexKeyDatum(_keyPattern, kv->key, _iam));
227-
_workingSet->transitionToRecordIdAndIdx(id);
227+
if (kv->record) {
228+
member->obj = {getOpCtx()->recoveryUnit()->getSnapshotId(), kv->record->releaseToBson()};
229+
_workingSet->transitionToRecordIdAndObj(id);
230+
} else {
231+
_workingSet->transitionToRecordIdAndIdx(id);
232+
}
228233

229234
if (_params.addKeyMetadata) {
230235
BSONObjBuilder bob;

src/mongo/db/index/index_access_method.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,9 @@ Status IndexAccessMethod::touch(OperationContext* opCtx) const {
257257
return _newInterface->touch(opCtx);
258258
}
259259

260-
RecordId IndexAccessMethod::findSingle(OperationContext* opCtx, const BSONObj& requestedKey) const {
260+
RecordId IndexAccessMethod::findSingle(OperationContext* opCtx,
261+
const BSONObj& requestedKey,
262+
RecordData* record) const {
261263
// Generate the key for this index.
262264
BSONObj actualKey;
263265
if (_btreeState->getCollator()) {
@@ -281,7 +283,9 @@ RecordId IndexAccessMethod::findSingle(OperationContext* opCtx, const BSONObj& r
281283
dassert(!kv->loc.isNull());
282284
dassert(kv->key.woCompare(actualKey, /*order*/ BSONObj(), /*considerFieldNames*/ false) ==
283285
0);
284-
286+
if (record) {
287+
*record = std::move(kv->record.value());
288+
}
285289
return kv->loc;
286290
}
287291

src/mongo/db/index/index_access_method.h

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
/**
2-
* Copyright (C) 2013-2014 MongoDB Inc.
3-
*
4-
* This program is free software: you can redistribute it and/or modify
5-
* it under the terms of the GNU Affero General Public License, version 3,
6-
* as published by the Free Software Foundation.
7-
*
8-
* This program is distributed in the hope that it will be useful,
9-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11-
* GNU Affero General Public License for more details.
12-
*
13-
* You should have received a copy of the GNU Affero General Public License
14-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15-
*
16-
* As a special exception, the copyright holders give permission to link the
17-
* code of portions of this program with the OpenSSL library under certain
18-
* conditions as described in each individual source file and distribute
19-
* linked combinations including the program with the OpenSSL library. You
20-
* must comply with the GNU Affero General Public License in all respects for
21-
* all of the code used other than as permitted herein. If you modify file(s)
22-
* with this exception, you may extend this exception to your version of the
23-
* file(s), but you are not obligated to do so. If you do not wish to do so,
24-
* delete this exception statement from your version. If you delete this
25-
* exception statement from all source files in the program, then also delete
26-
* it in the license file.
27-
*/
2+
* Copyright (C) 2013-2014 MongoDB Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License, version 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU Affero General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Affero General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*
16+
* As a special exception, the copyright holders give permission to link the
17+
* code of portions of this program with the OpenSSL library under certain
18+
* conditions as described in each individual source file and distribute
19+
* linked combinations including the program with the OpenSSL library. You
20+
* must comply with the GNU Affero General Public License in all respects for
21+
* all of the code used other than as permitted herein. If you modify file(s)
22+
* with this exception, you may extend this exception to your version of the
23+
* file(s), but you are not obligated to do so. If you do not wish to do so,
24+
* delete this exception statement from your version. If you delete this
25+
* exception statement from all source files in the program, then also delete
26+
* it in the license file.
27+
*/
2828

2929
#pragma once
3030

@@ -182,7 +182,9 @@ class IndexAccessMethod {
182182
*/
183183
long long getSpaceUsedBytes(OperationContext* opCtx) const;
184184

185-
RecordId findSingle(OperationContext* opCtx, const BSONObj& key) const;
185+
RecordId findSingle(OperationContext* opCtx,
186+
const BSONObj& key,
187+
RecordData* record = nullptr) const;
186188

187189
/**
188190
* Attempt compaction to regain disk space if the indexed record store supports

src/mongo/db/modules/eloq/src/eloq_index.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class EloqIndexCursor final : public SortedDataInterface::Cursor {
105105
_endKey = Eloq::MongoKey::GetNegInfTxKey();
106106

107107
_kvPair = &_ru->getKVPair();
108+
_recordPtr = nullptr;
108109
}
109110

110111
void setEndPosition(const BSONObj& key, bool inclusive) override {
@@ -234,19 +235,21 @@ class EloqIndexCursor final : public SortedDataInterface::Cursor {
234235
MONGO_LOG(1) << "finalKey" << finalKey;
235236

236237
_key.resetToKey(finalKey, _idx->ordering());
237-
_kvPair->keyRef().SetPackedKey(_key.getBuffer(), _key.getSize());
238-
std::string_view sv{_key.getBuffer(), _key.getSize()};
239-
bool isForWrite = _opCtx->isUpsert();
240-
auto [exists, err] =
241-
_ru->getKVInternal(_opCtx, *_indexName, _indexSchema->SchemaTs(), isForWrite);
238+
Eloq::MongoKey mongoKey(_key);
239+
auto [exists, err] = _ru->getKV(_opCtx,
240+
*_indexName,
241+
_indexSchema->SchemaTs(),
242+
&mongoKey,
243+
&_idReadRecord,
244+
_opCtx->isUpsert());
242245
uassertStatusOK(TxErrorCodeToMongoStatus(err));
243246
if (exists) {
244247
// valid
245248
_id = RecordId{_key.getBuffer(), _key.getSize()};
246249
_typeBits.reset();
250+
_recordPtr = &_idReadRecord;
247251
} else {
248252
_eof = true;
249-
_kvPair->setValuePtr(nullptr);
250253
}
251254

252255
return _curr(parts);
@@ -335,24 +338,25 @@ class EloqIndexCursor final : public SortedDataInterface::Cursor {
335338
BufReader br{_scanTupleRecord->UnpackInfoData(),
336339
static_cast<unsigned int>(_scanTupleRecord->UnpackInfoSize())};
337340
_typeBits.resetFromBuffer(&br);
338-
_kvPair->setValuePtr(_scanTupleRecord);
341+
_recordPtr = _scanTupleRecord;
339342
} break;
340-
341343
case IndexCursorType::UNIQUE: {
342344
_id = _scanTupleRecord->ToRecordId(false);
343345
BufReader br{_scanTupleRecord->UnpackInfoData(),
344346
static_cast<unsigned int>(_scanTupleRecord->UnpackInfoSize())};
345347
_typeBits.resetFromBuffer(&br);
346-
_kvPair->setValuePtr(nullptr);
348+
_recordPtr = nullptr;
347349
} break;
348-
349350
case IndexCursorType::STANDARD: {
350351
_id = KeyString::decodeRecordIdStrAtEnd(_key.getBuffer(), _key.getSize());
351352
BufReader br{_scanTupleRecord->UnpackInfoData(),
352353
static_cast<unsigned int>(_scanTupleRecord->UnpackInfoSize())};
353354
_typeBits.resetFromBuffer(&br);
354-
_kvPair->setValuePtr(nullptr);
355-
} break;
355+
_recordPtr = nullptr;
356+
break;
357+
}
358+
default:
359+
MONGO_UNREACHABLE;
356360
};
357361

358362
MONGO_LOG(1) << "EloqIndexCursor::_updateIdAndTypeBits " << _indexName->StringView()
@@ -372,7 +376,15 @@ class EloqIndexCursor final : public SortedDataInterface::Cursor {
372376
bson = KeyString::toBson(_key.getBuffer(), _key.getSize(), _idx->ordering(), _typeBits);
373377
MONGO_LOG(1) << "bson: " << bson << ". _id: " << _id;
374378
}
375-
return {{std::move(bson), _id}};
379+
380+
if (_recordPtr) {
381+
return {
382+
{std::move(bson),
383+
_id,
384+
{_recordPtr->EncodedBlobData(), static_cast<int>(_recordPtr->EncodedBlobSize())}}};
385+
} else {
386+
return {{std::move(bson), _id}};
387+
}
376388
}
377389

378390
bool _atOrPastEndPointAfterSeeking() const {
@@ -426,8 +438,11 @@ class EloqIndexCursor final : public SortedDataInterface::Cursor {
426438
txservice::TxKey _endKey;
427439
EloqKVPair* _kvPair;
428440

429-
Eloq::MongoKey _currentKey;
430-
Eloq::MongoRecord _currentRecord;
441+
// EloqDoc is index-organized table, we can bookeeping the record data here to avoid re-fetching
442+
// it.
443+
const Eloq::MongoRecord* _recordPtr;
444+
445+
Eloq::MongoRecord _idReadRecord;
431446

432447
boost::optional<EloqCursor> _cursor;
433448
};

src/mongo/db/modules/eloq/src/eloq_record_store.cpp

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -482,34 +482,28 @@ class EloqRecordStoreCursor : public SeekableRecordCursor {
482482
_cursor.reset();
483483
}
484484

485-
EloqKVPair& kvPair = _ru->getKVPair();
486-
Eloq::MongoKey& store_pkey = kvPair.keyRef();
487-
const Eloq::MongoRecord* store_record = kvPair.getValuePtr();
488-
489-
// _id don't need getKV if it has been stored in KVPair
490-
if (store_record == nullptr || store_pkey.PackedKeyStringView() != id.getStringView()) {
491-
store_pkey.SetPackedKey(id);
492-
bool isForWrite = _opCtx->isUpsert();
493-
auto [exists, err] =
494-
_ru->getKVInternal(_opCtx, *_tableName, _keySchema->SchemaTs(), isForWrite);
495-
uassertStatusOK(TxErrorCodeToMongoStatus(err));
496-
if (!exists) {
497-
MONGO_LOG(1) << "no found. id: " << id << ". Txservice error code: " << err;
498-
return {};
499-
}
500-
store_record = kvPair.getValuePtr();
501-
MONGO_LOG(1) << "keyStore:" << store_pkey.ToString();
485+
Eloq::MongoKey pkey(id);
486+
bool isForWrite = _opCtx->isUpsert();
487+
auto [exists, err] = _ru->getKV(
488+
_opCtx, *_tableName, _keySchema->SchemaTs(), &pkey, &_idReadRecord, isForWrite);
489+
uassertStatusOK(TxErrorCodeToMongoStatus(err));
490+
if (!exists) {
491+
MONGO_LOG(1) << "no found. id: " << id << ". Txservice error code: " << err;
492+
return {};
502493
}
503494

504495
if (_lastMongoKey) {
505-
_lastMongoKey->Copy(store_pkey);
496+
_lastMongoKey->Copy(pkey);
506497
} else {
507-
_lastMongoKey.emplace(store_pkey);
498+
_lastMongoKey.emplace(pkey);
508499
}
509500

501+
MONGO_LOG(1) << "found. id: " << id
502+
<< ". record:" << BSONObj{_idReadRecord.EncodedBlobData()}.jsonString();
503+
510504
return {
511505
{id,
512-
{store_record->EncodedBlobData(), static_cast<int>(store_record->EncodedBlobSize())}}};
506+
{_idReadRecord.EncodedBlobData(), static_cast<int>(_idReadRecord.EncodedBlobSize())}}};
513507
}
514508

515509
void saveUnpositioned() override {
@@ -599,6 +593,8 @@ class EloqRecordStoreCursor : public SeekableRecordCursor {
599593
txservice::TxKey _startKey;
600594
txservice::TxKey _endKey;
601595

596+
Eloq::MongoRecord _idReadRecord;
597+
602598
// Mongo use EloqRecordStoreCursor even for exact match operation
603599
// which actually does not need construct a Cursor in Eloq's design.
604600
// So use boost::optional to delay the contruction

src/mongo/db/storage/index_entry_comparison.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "mongo/bson/simple_bsonobj_comparator.h"
3636
#include "mongo/db/jsobj.h"
3737
#include "mongo/db/record_id.h"
38+
#include "mongo/db/storage/record_data.h"
3839

3940
namespace mongo {
4041

@@ -45,8 +46,16 @@ namespace mongo {
4546
struct IndexKeyEntry {
4647
IndexKeyEntry(BSONObj key, RecordId loc) : key(std::move(key)), loc(std::move(loc)) {}
4748

49+
IndexKeyEntry(BSONObj key, RecordId loc, RecordData record)
50+
: key(std::move(key)), loc(std::move(loc)), record(std::move(record)) {}
51+
4852
BSONObj key;
4953
RecordId loc;
54+
55+
/**
56+
* EloqDoc: Store record data along with index entry to avoid fetching from the main table.
57+
*/
58+
boost::optional<RecordData> record;
5059
};
5160

5261
std::ostream& operator<<(std::ostream& stream, const IndexKeyEntry& entry);

0 commit comments

Comments
 (0)