MongoDB $ set只写字段或整个文档吗?

时间:2014-03-13 09:26:06

标签: mongodb

我相信某个字段上的$inc只会更改该字段而不会重写整个文档。

我的问题是字符串字段上的$set(假设字符串长度相同)的行为方式是否相同。或者整个文档是否被重写?

通过扩展,replica-sets是复制整个记录还是以某种方式复制增量?

我很欣赏这是一个微优化问题。

3 个答案:

答案 0 :(得分:2)

这取决于。如果磁盘上已分配的块中有空格,它就会写入到位。如果没有空间,即文档超出其当前分配的空间,MongoDB将分配一个新空间并将文档移动到这个新位置。

如果要最小化文档移动,可以设置填充因子。然后MongoDB通过添加此paddingFactor来调整记录分配的大小,以便文档有增长的空间。有关 Record Padding 的更多信息。

关于副本集:副本集使用oplog(操作日志)进行操作。 Oplog上限集合(固定大小的集合,当它达到最大大小时会自动覆盖其最旧的条目),用于记录修改数据库中数据的所有操作的日志。辅助节点以异步方式复制和应用这些操作。任何副本集成员都可以从任何其他副本集成员的oplog中导入条目。

这意味着当您插入新文档时,该确切的更新操作将被复制到其他副本集成员并单独执行。涉及同一文档的任何后续更新都会发生同样的事情。以下是 MongoDB Replica Set Oplog 的信息。

答案 1 :(得分:1)

TL; DR:$inc保证就地更新,$set没有,但在非常具体的情况下,它也可以就地完成。

详细信息

这有两个方面:

  1. 它如何通过电线?

    信息作为操作发送,$set仍然是$set,因此它是一个增量。对于用于复制的oplog也是如此。通过这种方式,使用$set在带宽方面更有效。

  2. 如何在磁盘上更新?

    当且仅当键(字段)已存在时,MongoDB执行就地更新,因此当您向文档添加新字段时,这是一个更大的操作而不仅仅是为现有字段分配不同的值。

    然而,即便如此,这些值必须具有相同的大小,并且不能更改类型,并且必须是类型{{1 },否则当前就地更新。

  3. 我不确定后者在实践中是如何真正重要的,但服务器肯定会为这两者使用完全不同的代码路径,因此它可以导致字段重新排序。对于非常大的文档,这可能会导致性能上存在可测量的差异。

    这表明double, long, int or bool是非常不同的,因为它只允许那些肯定就地的操作,因为$inc只对数字类型进行操作,并且自然不能改变大小或类型。

答案 2 :(得分:0)

  

我的问题是字符串字段是否设置$

假设大小没有变化,正如你所说,MongoDB只会更新内存中的那个字段,然后将字段保存回文档。

  

通过扩展,replica-sets是复制整个记录还是以某种方式复制增量?

副本集通过从oplog中选择,将相同的操作应用于主要操作。

因此,如果主要应用了就地更新,那么集合中的所有成员也将更新。