使用MongoDB与MySQL有很多JSON字段?

Dhr*_*hak 22 mysql mongodb nosql

有一种微博类型的应用程序.默认的两个主要基本数据库存储是:MySQL或MongoDB.

我计划对大量数据进行反规范化即将对帖子进行的投票存储在投票表中,同时计数也会在主帖子表中递增.该帖还涉及其他行动(例如,喜欢,投票放弃).

如果我使用MySQL,一些数据更适合作为JSON而不是固定模式,以便更快地进行查找.

例如

POST_ID   |  activity_data

213423424 | { 'likes': {'count':213,'recent_likers' :
             ['john','jack',..fixed list of recent N users]} , 'smiles' : 
             {'count':345,'recent_smilers' :
             ['mary','jack',..fixed list of recent N users]}  }
Run Code Online (Sandbox Code Playgroud)

该应用程序还有其他组件,其中提出了JSON的使用.因此,要更新JSON字段,序列为:

  1. 阅读python脚本中的JSON.

  2. 更新JSON

  3. 将JSON存储回MySQL.

这本来是MongoDB中单次操作与像原子操作$push,$inc,$pull等等.同样的MongoDB的文档结构适合我的数据很好.

我在选择数据存储时的注意事项.

关于MySQL:

  1. 稳定而熟悉.
  2. 备份和恢复很容易.
  3. 使用某些字段作为无模式JSON可以避免某些未来的模式更改.
  4. 可能要早点使用memcached层.
  5. JSON blobs在一些表中将是静态的,例如主帖,但是在其他一些表中会更新,比如Post投票和喜欢.

关于MongoDB:

  1. 更适合将架构较少的数据存储为文档.
  2. 可以避免缓存直到稍后阶段.
  3. 有时应用程序可能会变得更加密集,MongoDB可以在不安全写入不成问题的那些点上表现更好.
  4. 不确定稳定性和可靠性.
  5. 不确定备份和恢复有多容易.

问题:

  1. 如果有一半数据是无模式的,我们应该选择MongoDB吗?如果使用MySQL,我们是否存储为JSON?
  2. 一些数据如主帖是关键的,所以它将使用安全写入保存,计数器等将使用不安全写入保存.此政策是否基于数据的重要性,写密集性是否正确?

  3. 与MySQL相比,监控,备份和恢复MongoDB有多容易?我们需要计划定期备份(比如每天),并在发生灾难时轻松恢复.我与MongoDB有什么最好的选择,使它成为应用程序的安全赌注.

稳定性,备份,快照,恢复,更广泛的采用Iedatabase持久性是指向我使用MySQL作为RDBMS + NoSql的原因,即使NoSQL文档存储可以更好地服务于我的目的.

考虑到我想到的数据库设计,请关注MySQL和MongoDB之间的选择.我知道可以有更好的方法来使用RDBMS或MongoDB文档来规划数据库设计.但这不是我问题的当前焦点.

更新:从MySQL 5.7开始,MySQL支持丰富的本机JSON数据类型,它提供了数据灵活性以及丰富的JSON查询.

https://dev.mysql.com/doc/refman/5.7/en/json.html

Fuw*_*jax 18

所以,直接回答问题......

如果有一半数据是无模式的,我们应该选择mongodb吗?如果使用MySQL,我们会选择存储为JSON吗?

无模式存储肯定是使用MongoDB的一个令人信服的理由,但正如您所指出的,将JSON存储在RDBMS中也相当容易.MongoDB背后的力量在于对无模式存储的丰富查询.

如果我可以指出关于更新JSON字段的插图中的一个小缺陷,那不仅仅是获取当前值,更新文档然后将其推回数据库.该过程必须全部包含在事务中.在您开始对数据库进行非规范化之前,事务往往相当简单.然后像记录upvote这样简单的东西可以锁定整个模式的表.

使用MongoDB,没有事务.但是,操作几乎总是以允许原子更新的方式构建.这通常涉及SQL范例的一些戏剧性转变,但在我看来,一旦你停止尝试强制对象进入表格,它们就相当明显.至少,许多其他人遇到了你将面临的同样问题,而Mongo社区往往对他们所克服的挑战相当开放和直言不讳.

一些数据如主帖是关键的,所以它将使用安全写入保存,计数器等将使用不安全写入保存.此政策是否基于数据的重要性,写密集性是否正确?

通过"安全写入",我假设您的意思是在每次写入后打开自动"getLastError()"的选项.我们在DBCollection上有一个非常薄的包装器,允许我们在调用getLastError()时进行细粒度控制.但是,我们的策略不是基于"重要"数据的方式,而是基于查询后面的代码是否期望在以下读取中立即可见任何修改.

一般来说,这仍然是一个糟糕的指标,我们已经迁移到findAndModify()以获得相同的行为.在我们仍然显式调用getLastError()的情况下,当数据库可能拒绝写入时,例如当我们使用可能重复的_id insert()时.

与mysql相比,监视,备份和恢复Mongodb有多容易?我们需要计划定期备份(比如每天),并在发生灾难时轻松恢复.我有什么最好的选择mongoDb使它成为应用程序的安全赌注?

我担心我的备份/恢复策略是否有效,因为我们还没有恢复.我们正在遵循MongoDB的备份建议; @ mark-hillick在总结这些方面做得很好.我们正在使用副本集,我们已经迁移了MongoDB版本以及引入了新的副本成员.到目前为止,我们没有停机时间,所以我不确定我能说得好.

稳定性,备份,快照,恢复,更广泛的采用数据库持久性是指向我使用MySQL作为RDBMS + NoSql的原因,即使NoSQL文档存储可以更好地服务于我的目的.

因此,根据我的经验,MongoDB提供了无模式数据的存储,其中包含一组足够丰富的查询原语,以便通常可以用原子操作替换事务.很难忘掉10年以上的SQL经验,但我遇到的每个问题都已经由社区或10gen直接解决.我们没有丢失数据或没有任何我能记得的停机时间.

简而言之,MongoDB是我在查询,维护,可扩展性和可靠性方面所使用的最佳数据存储生态系统.除非我有一个非常明确的关系应用程序,否则我不能使用除SQL以外的任何东西,我会尽一切努力使用MongoDB.

我不为10gen工作,但我非常感谢那些做过的人.


Mar*_*ick 13

我不打算对比较做评论(我为10gen工作并且认为这对我来说不合适),但是,我将回答具体的MongoDB问题,以便您可以更好地做出决定.

备份

这里的文档非常详尽,涵盖了很多方面:

  • 块级方法(LVM使它非常简单,很多人都这样做)
  • 有/没有日记
  • EBS快照
  • 一般快照
  • 复制(技术上没有备份,但很多人使用副本集来实现冗余和备份 - 不建议这样做但是已经完成了)

直到最近,没有MongoDB相当于mylvmbackup一个好人写了一个:)在他的话

到目前为止的早期:它只是一个美化的shell脚本,需要更多的错误检查.但它已经对我有用了,我想我会分享快乐.欢迎提供错误报告,补丁和建议.

这里获取一份副本.

还原

mongodump完全记录在这里,mongorestore在这里.

mongodump不包含索引但包含system.indexes集合,因此mongorestore可以在还原bson文件时重建索引.bson文件是实际数据,mongoexport/mongoimport但不是类型安全的所以它可以是任何东西(从技术上讲):)

监控

记录在这里.

我喜欢Cacti,但afaik,Cacti模板没有跟上MongoDB中的变化,因此依赖于旧的语法,所以发布2.0.4后,我相信存在问题.

Nagios运作良好,但它是Nagios,所以你要么爱,要么恨它.很多人都使用Nagios,它似乎为他们提供了极大的可见性.

我听说有些人看着Zappix但是我从来没有用过它所以不能发表评论.

此外,您可以使用MMS,它是免费的,并在外部托管.您的MongoDB实例运行代理,其中一个代理通过https与mms.10gen.com进行通信(使用python代码).我们使用MMS来查看MongoDB实例的所有性能统计数据,从高级别的广泛视图以及提供向下钻取的能力非常有用.它安装简单,您不必为此运行任何硬件.许多客户运行它,有些客户使用Cacti/Nagios.

有关MMS的帮助信息可以在这里找到(这是一份非常详细的,包容性的文件).

  • 我想补充一点,你应该考虑复制集和自动故障转移等功能的可靠性.它不仅提供冗余的数据最新副本,在完全丢失主服务器的情况下,您希望立即进行故障转移,而不是在还原最新备份时需要接受停机和数据丢失. (3认同)

Dav*_*idA 5

存储 json 的 mysql 解决方案的缺点之一是您将无法有效地搜索 json 数据。如果您将其全部存储在 mongodb 中,则可以对包括 json 在内的所有数据创建索引和/或查询。

Mongo 的写入工作得很好,与 mysql 相比,您真正失去的唯一一件事就是事务支持,因此回滚多部分保存的能力。但是,如果您能够在原子操作中提交更改,那么就不存在数据安全问题。如果您被复制,mongo 会提供“最终一致”的承诺,以便从服务器最终会镜像主服务器。

Mongodb 不提供某些 db 构造(例如外键)的本地实施或级联,因此您必须自己管理这些构造(例如通过组合,这是 mongo 的优势之一),或通过使用 dbrefs。

如果您确实需要事务支持和健壮的“安全”写入,但仍需要 nosql 提供的灵活性,您可以考虑使用混合解决方案。这将允许您使用 mysql 作为您的主要帖子存储,然后使用 mongodb 作为您的“无模式”存储。这是讨论混合 mongo/rdbms 解决方案的文档的链接: http ://www.10gen.com/events/hybrid-applications 该文章来自 10gen 的站点,但您可以通过快速 google 搜索找到其他示例。

2019 年 5 月 28 日更新

自从发布这个答案以来,MySQL 和 Mongodb 都发生了许多变化,因此它们之间的优缺点变得更加模糊。此更新对原始问题没有真正帮助,但我这样做是为了确保任何新读者都能获得更多最新信息。

MongoDB 现在支持事务:https : //docs.mongodb.com/manual/core/transactions/

MySql 现在支持索引和搜索 json 字段:https : //dev.mysql.com/doc/refman/5.7/en/json.html

  • 只是在这里更正 - 没有写给奴隶这样的事情。并且 mongo 并不是最终一致的——默认情况下它是强一致的(或读取一致的)——只有当你明确地指示你的应用程序从辅助读取时才会出现最终的一致性语义。事实上,有一个安全写入级别只会在数据已写入主要 * 并且* 成功复制到指定数量的辅助设备时才会确认成功。 (2认同)
  • 根据您当前的要求,考虑到您已经熟悉并熟悉 MySQL,我认为使用 MongoDB 或基于 MySQL 的混合解决方案没有明显令人信服的理由。 (2认同)