【问题标题】:Which is the right database for the job?哪个数据库适合这项工作?
【发布时间】:2011-08-19 06:51:37
【问题描述】:

我正在开发一项功能,并且可以就我应该使用哪个数据库来解决这个问题提出意见。

我们有一个使用 MySQL 的 Rails 应用程序。我们对 MySQL 没有任何问题,它运行良好。但是对于一个新特性,我们正在决定是否保留 MySQL。为了简化问题,我们假设有UserMessage 模型。用户可以创建消息。消息会根据其他用户与发布者的关联传递给其他用户。

显然存在基于友谊的关联,但还有更多基于用户个人资料的关联。我计划将一些关于海报的元数据与消息一起存储。这样我就不用每次查询消息时都拉取元数据了。

因此,消息可能如下所示:

{
  id: 1,
  message: "Hi",
  created_at: 1234567890,
  metadata: {
    user_id: 555,
    category_1: null,
    category_2: null,
    category_3: null,
    ...
  }
}

当我查询消息时,我需要能够基于零个或多个元数据属性进行查询。此调用需要快速且经常发生。

由于元数据属性的数量以及查询中可以包含任意数量的事实,在此处创建 SQL 索引似乎不是一个好主意。

就个人而言,我有使用 MySQL 和 MongoDB 的经验。我已经开始研究 Cassandra、HBase、Riak 和 CouchDB。我可以从可能已经研究过哪个数据库适合我的任务的人那里获得一些帮助。

是的,messages 表很容易增长到数百万行。

【问题讨论】:

    标签: mysql mongodb couchdb riak nosql


    【解决方案1】:

    这是一个非常开放的问题,所以我们所能做的就是根据经验提供建议。首先要考虑的是,决定使用以前没有使用过的东西而不是使用您熟悉的 MySQL 是否是个好主意。当你有机会时不使用闪亮的新东西很无聊,但相信我,当你把自己画在角落里时会很糟糕,因为你认为新玩具会按照盒子上说的一切来做。没有什么能像博客文章中所说的那样奏效。

    我主要有 MongoDB 方面的经验。这是一个糟糕的选择,除非你想花很多时间尝试不同的事情并意识到它们不起作用。一旦你扩大了一点,你基本上就不能使用二级索引、更新和其他使 Mongo 成为一个非常好的工具的东西(其中大部分与它的全局写锁和磁盘上的数据库格式有关,它如果您删除数据,基本上很容易处理并发和碎片)。

    我不同意 HBase 是不可能的,它没有二级索引,但是一旦超过一定的流量负载,你就不能使用它们。 Cassandra 也是如此(它比 HBase 更容易部署和使用)。基本上,无论您选择哪种解决方案,您都必须实施自己的索引。

    您应该考虑的是,您是否需要在可用性方面保持一致性,反之亦然(例如,如果消息丢失或延迟有多糟糕,而如果用户无法发布或阅读消息会有多糟糕),或者如果您要对数据进行更新(例如,Riak 中的数据是一个不透明的 blob,要更改它,您需要读取它并将其写回,在 Cassandra、HBase 和 MongoDB 中,您可以添加和删除属性而无需先读取目的)。易用性也是一个重要因素,从程序员的角度来看,Mongo 肯定好用,而 HBase 很烂,但只要花点时间自己做一个封装了讨厌的东西的库,就值得了。

    最后,别听我的,试一试,看看他们的表现和感觉如何。确保您尽可能努力地加载它,并确保您测试您将要做的所有事情。我犯了一个错误,没有测试当您在 MongoDB 中删除大量数据时会发生什么,并且为此付出了高昂的代价。

    【讨论】:

      【解决方案2】:

      我建议您查看有关Why databases suck for messaging 的演示文稿,该演示文稿主要针对您不应使用 MySQL 等数据库进行消息传递的事实。

      我认为在这种情况下,CouchDB 的changes feed 可能会派上用场,尽管您可能还必须根据查询消息元数据创建一些更复杂的views。如果速度很关键,请尝试查看redis,它非常快并且带有pub/sub 功能。具有即席查询支持的 MongoDB 也可能是此用例的不错解决方案。

      【讨论】:

        【解决方案3】:

        我认为您在将元数据与每条消息一起存储方面非常出色!牺牲存储以加快检索时间可能是要走的路。请注意,如果您需要更改用户的元数据并将其传播到所有消息,它可能会变得复杂。您应该考虑这可能发生的频率,是否真的需要更新所有消息记录,以及基于此是否值得为减少查询而付出代价(这可能是值得的,但这取决于系统的细节)。

        我同意@Andrej_L 的观点,即 Hbase 不是解决此问题的正确方法。 Cassandra 也是出于同样的原因。

        CouchDB 可以解决您的问题,但是您必须为要查询的任何元数据定义视图(物化索引)。如果这里不使用 MySQL 的全部目的是避免索引所有内容,那么 Couch 可能也不是正确的解决方案。

        Riak 将是一个更好的选择,因为它使用 map-reduce 查询您的数据。这使您可以构建您喜欢的任何查询,而无需像在沙发上那样预先索引所有数据。对于 Riak 来说,数百万行不是问题 - 不用担心。如果需要,它也可以通过简单地添加更多节点来很好地扩展(它也可以自我平衡,所以这真的不是问题)。

        所以根据我自己的经验,我会推荐 Riak。但是,与您不同的是,我对 MongoDB 没有直接经验,因此您必须自己再次判断 Riak(或者这里的其他人可以回答)。

        【讨论】:

        • 最好的部分是,我不必担心元数据的变化。一旦使用元数据创建了一条消息,它就为该消息设置了石头。
        【解决方案4】:

        根据我使用 Hbase 的经验,这对于您的应用程序来说并不是一个好的解决方案。 因为:

        1. 默认不包含二级索引(你应该安装插件或类似的东西)。所以你只能通过主键有效地搜索。我已经使用 hbase 和附加表实现了二级索引。所以你不能在在线应用程序中使用这个,因为要获得结果你应该运行 map/reduce 作业,这将花费大量时间处理百万数据。

        2. 这个数据库很难支持和调整。为了有效地工作,您需要将 HBAse 与 Hadoop 结合使用,并且需要功能强大的计算机或多台计算机。

        3. 当您需要对大量数据进行聚合报告时,Hbase 非常有用。好像不需要。

        【讨论】:

          【解决方案5】:

          由于元数据属性的数量以及任何数量都可以 被包含在查询中,在这里创建 SQL 索引似乎不像 好主意。

          听起来您需要加入,因此您几乎可以忘记 CouchDB,直到他们整理出已处理的多视图代码(实际上不确定它是否仍在处理)。

          【讨论】:

          • 这只是一个一级关系。所以加入不是唯一的选择。您可以:a) 将用户的记录#嵌入到消息记录中或 b) 嵌入元数据,因此您不必查找用户记录
          【解决方案6】:

          Riak 可以尽可能快地查询,具体取决于节点

          Mongo 将允许您在任何字段上创建索引,即使它是一个数组

          CouchDB 非常不同,它使用存储的 Map-Reduce(但没有 reduce)构建索引,他们称之为“视图”

          RethinkDB 将让您拥有 SQL,但速度更快 TokuDB 也会

          Redis 会在速度上扼杀一切,但它完全存储在 RAM 中

          单级关系可以在所有这些中完成,但对每个都不同。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-17
            • 1970-01-01
            相关资源
            最近更新 更多