Reputation: 283
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
Reputation: 46311
TL;DR: $inc
guarantees in-place updates, $set
doesn't, but under very specific circumstances it can also be done in-place.
There are two aspects to this:
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.
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
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
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