BobR
BobR

Reputation: 283

Does MongoDB $set write just the field or the whole document?

I believe that $inc on a field changes just that field in place without rewriting the whole document.

My question is whether a $set on a string field (assuming the string is the same length) behaves the same way. Or does the whole document get rewritten?

By extension, do replica-sets copy the whole record or somehow just the deltas?

I appreciate that this is a micro-optimization question.

Upvotes: 2

Views: 902

Answers (3)

mnemosyn
mnemosyn

Reputation: 46311

TL;DR: $inc guarantees in-place updates, $set doesn't, but under very specific circumstances it can also be done in-place.

Details

There are two aspects to this:

  1. how does it go over the wire?

    The information is sent as an operation, a $set remains a $set so it's a delta. That is also true for the oplog that is used for replication. In this way, using $set is more efficient with respect to bandwidth.

  2. how is it updated on disk?

    MongoDB performs an in-place update if and only if the key (field) already exists, so when you add a new field to a document, that's a larger operation than just assigning a different value to an existing field.

    Even then, however, the values must have the same size and must not change type and they must be of type double, long, int or bool, otherwise it's not an in-place update currently.

I'm not sure how the latter is really important in practice, but the server definitely uses completely different code paths for the two, so it can for instance lead to field re-ordering. For very large documents, that will probably result in a measurable difference in performance.

This shows that $inc is very different in that it only allows operations which are certainly in-place, because $inc only operates on numeric types and can't change size or type, naturally.

Upvotes: 1

user508434
user508434

Reputation:

It depends. If there is a space in the allocated blocks on the disk it will just write in place. If there is no space, i.e. a document outgrows its current allocated space, MongoDB allocates a new space and moves the document to this new location.

If you want to minimize document movement, you can set a padding factor. Then MongoDB adjusts the size of record allocations by adding this paddingFactor so that the documents have room to grow. More about Record Padding.

About replica sets: replica sets operates using the oplog (operations log). Oplog is a capped collection (fixed-sized collection that automatically overwrites its oldest entries when it reaches its maximum size) that keeps a log of all operations that modify data in your database. The secondary nodes copy and apply these operations in an asynchronous manner. Any replica set member can import entries from oplog from any other replica set member.

This means when you insert a new document, that exact update operation is copied over to other replica set members and are executed individually. The same thing happens with any subsequent updates involving the same document. Here is info about MongoDB Replica Set Oplog.

Upvotes: 2

Sammaye
Sammaye

Reputation: 43884

My question is whether a $set on a string field

Assuming there is no change in size, as you say, MongoDB will only update that field in memory and then save the field back into the document.

By extension, do replica-sets copy the whole record or somehow just the deltas?

Replica sets apply the same op to themselves as the primary did via picking from the oplog.

As such if the primary applied an in place update so too will all members of the set.

Upvotes: 0

Related Questions