前言

分片,唯一索引和upsert,表面上看似没有直接联系的几个东西,到底存在怎样的瓜葛呢?

分片

为了保持水平扩展的有效性,分片功能必须保证各个片之间没有直接关联,不需要与其他分片交互就可以独立做出决策。如果不能满足这一点,随着分片数量不断增加,需要交互的分片越来越多,势必会越来越慢,那么就违背了分片的初衷了。比如JOIN就是一种典型的破坏分片独立性的功能。在一个n个分片的集群中,为了得到笛卡尔积,每个分片必须与其他n-1个分片交互来得到结果。虽然不见得是线性的延迟增长(因为n-1个请求可以并行),但是可想而知对资源将是极大的消耗,并且随着分片数量的增长影响会越来越显著,最终会到达“增加一个分片可能对性能完全没有帮助”,或者“增加一个分片反而降低性能”的地步。

唯一索引

唯一索引是另外一个显著破坏分片独立性的特性。前面对JOIN的分析完全适用于唯一索引,并且更糟的情况是唯一索引还有有更进一步的恶劣影响,那就是在写入数据的时候必须占用一个跨分片的全局锁,否则无法保证其唯一性,可想而知对性能有怎样的影响。这也是MongoDB为什么不打算去实现全局唯一索引的原因。

有一种特殊情况却可以改变这种不利状况,那就是唯一索引的键正好是片键的时候。片键一旦确定,文档该去哪个分片就确定了,那么只要保证该键在这一个片上唯一就可以了,不再需要去与其他分片协商。

upsert

从语义上讲,我们使用upsert一般是希望一个键只出现一次的(不然每次insert就好了)。这一点恰恰是唯一索引要干的事情,而唯一索引又存在上面的所说的问题,因此唯一有意义的情况则是upsert使用的条件正好是片键,且片键唯一。
满足了上面这些条件就高枕无忧了吗?并不是。在决定一个键是不是存在,到执行update/insert之间,是存在空隙的。即,检测和执行并不在一个原子操作中,也不可能在一个原子操作中,否则将是一个很大粒度的锁。再说,MongoDB对文档级别并没有真正通过加锁来控制,而是通过“乐观并发控制”(optimistic concurrency control)来进行的。
因此,出于效率考虑,不是原子操作是正确的选择,而解决这个问题也不是特别麻烦的事情,实际上只需要在遇到duplicate key异常的时候重试该操作就可以了,因为重试的时候理论上就应该变成update而不再是insert,自然避免了问题。或者,在4.2中直接实现了这类错误的自动重试(SERVER-37124)。

参考资料

MongoDB分片,唯一索引与upsert的更多相关文章

  1. TokuMX唯一索引不支持dropDups选项

    TokuMX v1.5.0的唯一索引(unique index)不支持dropDups选项, 如果源数据包含相同目标key的文档,将无法建立唯一索引. 问题场景: 从MongoDB到TokuMX的数据 ...

  2. MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划

    这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...

  3. MongoDB 创建基础索引、组合索引、唯一索引以及优化

    一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存在system.indexes 中,且默认总是为_id创建索引,它的索引使用基本和MySQL 等关系型数据库一样.其实可以这样说说,索引 ...

  4. MongoDB小结25 - 复合唯一索引

    只要满足索引的其中之一不同即可 db.blog.ensureIndex({"username":1,"blogname":1}) 作者和作品名其中之一不同即可创 ...

  5. MongoDB的复合唯一索引

    一 创建 JavaScript Shell db.room.ensureIndex({'floor':1,'num':1}) Spring Data @Data // lombok @Document ...

  6. mongodb 索引,全文索引与唯一索引

    唯一索引创建: db.createIndex({name: 1}, {unique: true})

  7. MongoDB(课时22 唯一索引)

    3.6.1 唯一索引 唯一索引的主要目的是用在某一个字段上,使该字段的内容不重复. 范例:创建唯一索引 db.students.ensureIndex({"name" : 1}, ...

  8. 4.非关系型数据库(Nosql)之mongodb:普通索引,唯一索引

     一:普通索引 1创建一个新的数据库 > use toto; switched to db toto > show dbs; admin (empty) local 0.078GB & ...

  9. MongoDB 分片管理(不定时更新)

    背景: 通过上一篇的 MongoDB 分片的原理.搭建.应用 大致了解了MongoDB分片的安装和一些基本的使用情况,现在来说明下如何管理和优化MongoDB分片的使用. 知识点: 1) 分片的配置和 ...

随机推荐

  1. python合并字典

    给定一个字典,然后计算它们所有数字值的和. 实例 1 : 使用 update() 方法,第二个参数合并第一个参数 def Merge(dict1, dict2): return(dict2.updat ...

  2. manacher算法笔记

    模板 [模板]manacher算法 不妨先只考虑如何求长度为奇数的回文串 记\(P[i]\)表示以\(i\)为中心最多向两边扩展几个字符,满足回文 如串\(ababa\), \(P[1]=0,P[2] ...

  3. mysql 主从 数据不一致

    用pt-table-checksum校验数据一致性 Jun 4th, 2013 主从数据的一致性校验是个头疼的问题,偶尔被业务投诉主从数据不一致,或者几个从库之间的 数据不一致,这会令人沮丧.通常我们 ...

  4. 2018-2019-2 20165315《网络对抗技术》Exp7 网络欺诈防范

    2018-2019-2 20165315<网络对抗技术>Exp7 网络欺诈防范 一.实验内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 简单应 ...

  5. 记一次Pr字幕模糊问题及解决方法

    目录 问题: 解决: 问题: 1.导出视频后,发现字幕很模糊 2.发现我们导出时的设置如下图,画面大小为432x244 3.即使暴力修改宽度为1080,导出画面的清晰度也不会有什么变化. 解决: 1. ...

  6. Proxy代理对象是如何调用invoke()方法的.

    直奔主题,不说废话.先看java使用Proxy创建代理对象的代码. //一个开发者接口public interface Developer { String code(); void debug(); ...

  7. Tensorflow2 快速简单安装命令

    使用如下命令 pip3 install numpy pandas matplotlib sklearn tensorflow==2.0.0-alpha0 -i https://pypi.doubani ...

  8. JavaScript的这个缺陷,让多少程序员为之抓狂?

    相信提到JavaScript语言,每一个程序员的心理状态都是不一样的,有的对此深恶痛绝,有的又觉得其可圈可点,造成这种两级分化态度的原因还是由于其自身类型约束上的缺陷,直到现如今依旧无法解决. 本文由 ...

  9. 你不知道的js——数组 join

    你可能对使用数组的 join 方法已经轻车熟路,但你也许不知道: 10.If element0 is undefined or null, let R be the empty String; oth ...

  10. [转帖]统一操作系统 UOS 龙芯版上线

    统一操作系统 UOS 龙芯版上线 看评论很有必要 搞一波 深度的操作系统了https://www.oschina.net/news/112065/chinauos-with-loongson?p=4 ...