@@ -247,17 +247,20 @@ Status IndexBuildInterceptor::_applyWrite(OperationContext* opCtx,
247247 const InsertDeleteOptions& options,
248248 int64_t * const keysInserted,
249249 int64_t * const keysDeleted) {
250- const BSONObj key = operation[" key" ].Obj ();
251- const RecordId opRecordId = RecordId (operation[" recordId" ].Long ());
250+ // Deserialize the encoded KeyString::Value.
251+ int keyLen;
252+ const char * binKey = operation[" key" ].binData (keyLen);
253+ BufReader reader (binKey, keyLen);
254+ const KeyString::Value keyString = KeyString::Value::deserialize (
255+ reader,
256+ _indexCatalogEntry->accessMethod ()->getSortedDataInterface ()->getKeyStringVersion ());
257+
252258 const Op opType =
253259 (strcmp (operation.getStringField (" op" ), " i" ) == 0 ) ? Op::kInsert : Op::kDelete ;
254260
255- KeyString::HeapBuilder keyString (
256- _indexCatalogEntry->accessMethod ()->getSortedDataInterface ()->getKeyStringVersion (),
257- key,
258- _indexCatalogEntry->ordering (),
259- opRecordId);
260- const KeyStringSet keySet{keyString.release ()};
261+ const KeyStringSet keySet{keyString};
262+ const RecordId opRecordId =
263+ KeyString::decodeRecordIdAtEnd (keyString.getBuffer (), keyString.getSize ());
261264
262265 auto accessMethod = _indexCatalogEntry->accessMethod ();
263266 if (opType == Op::kInsert ) {
@@ -398,29 +401,36 @@ Status IndexBuildInterceptor::sideWrite(OperationContext* opCtx,
398401 return Status::OK ();
399402 }
400403
404+ // Reuse the same builder to avoid an allocation per key.
405+ BufBuilder builder;
401406 std::vector<BSONObj> toInsert;
402407 for (const auto & keyString : keys) {
403408 // Documents inserted into this table must be consumed in insert-order.
404409 // Additionally, these writes should be timestamped with the same timestamps that the
405410 // other writes making up this operation are given. When index builds can cope with
406411 // replication rollbacks, side table writes associated with a CUD operation should
407412 // remain/rollback along with the corresponding oplog entry.
408- auto key = KeyString::toBson (keyString, _indexCatalogEntry->ordering ());
409- toInsert.emplace_back (BSON (" op" << (op == Op::kInsert ? " i" : " d" ) << " key" << key
410- << " recordId" << loc.repr ()));
413+
414+ // Serialize the KeyString::Value into a binary format for storage. Since the
415+ // KeyString::Value also contains TypeBits information, it is not sufficient to just read
416+ // from getBuffer().
417+ builder.reset ();
418+ keyString.serialize (builder);
419+ BSONBinData binData (builder.buf (), builder.getSize (), BinDataGeneral);
420+ toInsert.emplace_back (BSON (" op" << (op == Op::kInsert ? " i" : " d" ) << " key" << binData));
411421 }
412422
413423 if (op == Op::kInsert ) {
414424 // Wildcard indexes write multikey path information, typically part of the catalog
415425 // document, to the index itself. Multikey information is never deleted, so we only need
416426 // to add this data on the insert path.
417427 for (const auto & keyString : multikeyMetadataKeys) {
418- auto key = KeyString::toBson (keyString, _indexCatalogEntry->ordering ());
428+ builder.reset ();
429+ keyString.serialize (builder);
430+ BSONBinData binData (builder.buf (), builder.getSize (), BinDataGeneral);
419431 toInsert.emplace_back (BSON (" op"
420432 << " i"
421- << " key" << key << " recordId"
422- << static_cast <int64_t >(
423- RecordId::ReservedId::kWildcardMultikeyMetadataId )));
433+ << " key" << binData));
424434 }
425435 }
426436
0 commit comments