【问题标题】:MongoDB sharding scalability - performance of queries hitting a single chunk?MongoDB 分片可扩展性 - 查询单个块的性能?
【发布时间】:2011-11-30 01:38:42
【问题描述】:

在对 MongoDB 分片进行一些初步测试时,我希望并期望随着更多数据的加载,在一个分片/机器上执行仅命中单个数据块的查询的时间将保持相对恒定。但我发现速度明显放缓。

一些细节:

对于我的简单测试,我使用两台机器进行分片,并尝试对具有 200 万行和 700 万行的类似集合进行查询。这些显然是非常小的集合,甚至不需要分片,但我很惊讶已经看到查询只命中单个块的显着一致减速。查询包括分片键,用于从 10 到 100000 行的结果集,我测量了滚动整个结果集所需的总时间。另一件事:由于我的应用程序实际上需要的数据量远远超过 RAM 的容量,因此所有查询都是基于冷缓存进行计时的。

知道为什么会这样吗?有没有其他人观察到相同或矛盾的结果?


更多细节(由 Theo 提示):

对于这个测试,行很小(包括 _id 在内的 5 列),并且键不是基于 _id,而是基于几乎总是出现在查询中的多值文本列。

命令 db.printShardingStatus() 显示有多少块以及用于分割块范围的确切键值。该数据集的平均块包含超过 100,000 行,并且检查键值拆分可验证测试查询是否命中单个块。

出于本次测试的目的,我只测量了读数。没有插入或更新。


更新:

通过一些额外的研究,我相信我确定了减速的原因:MongoDB 块纯粹是逻辑的,并且它们中的数据在物理上并不是一起放置的(来源:Kristina Chodorow 的“Scaling MongoDB”)。这与 Oracle 和 MySQL 等传统数据库中的分区不同。这似乎是一个很大的限制,因为分片将随着分片/机器的添加而水平扩展,但在垂直维度上不太好,因为数据被添加到具有固定数量分片的集合中。

如果我正确理解这一点,如果我有 1 个集合,其中有 10 亿行分片在 10 个分片/机器上,那么即使只命中一个分片/机器的查询仍在从 1 亿行的大集合中进行查询。如果分片键的值恰好位于磁盘上,那可能没问题。但如果不是,并且我获取的行数超过几行(例如 1000 行),那么这似乎可能会导致大量 I/O 问题。

所以我的新问题是:为什么不在 MongoDB 中物理组织块以实现垂直和水平可扩展性?

【问题讨论】:

    标签: mongodb sharding


    【解决方案1】:

    免责声明:我在 Tokutek 工作

    所以我的新问题是:为什么不在 MongoDB 中物理组织块以实现垂直和水平可扩展性?

    这正是TokuMX 所做的,它是 MongoDB 的替代服务器。 TokuMX 使用具有高写入吞吐量和压缩率的分形树索引,因此数据不是存储在堆中,而是clustered with the index。默认情况下,shard key 是集群的,因此它完全按照您的建议进行操作,它通过确保所有文档按磁盘上的 shard key 排序来物理组织块。这使得对分片键的范围查询快速,就像在任何聚集索引上一样。

    【讨论】:

      【解决方案2】:

      是什么让您说查询只涉及一个块?如果结果范围高达 100 000 行,这听起来不太可能。一个块最大为 64 Mb,除非你的对象很小,否则很多都不适合。 Mongo 很可能已经拆分了你的块并分发了它们。

      我认为您需要告诉我们更多关于您在做什么以及您的数据形式的信息。您是否同时查询和加载?当您说块时,您是指碎片吗?你的分片键不是_id吗?您在查询数据时是否进行任何更新?

      Mongo 的性能有两个主要因素:全局写锁和内存映射文件的使用。内存映射文件意味着你真的必须考虑你的使用模式,并且全局写锁会使页面错误受到非常严重的伤害。

      如果您查询的东西遍布整个操作系统将难以将内容分页进出,如果您的对象很小,这可能会特别有害,因为必须加载整个页面才能访问小块,很多RAM 将被浪费。如果您正在执行大量写入会锁定读取(但通常不会那么糟糕,因为写入相当顺序地发生) - 但是如果您正在执行更新,您可能会忘记任何类型的性能,更新会阻塞整个数据库服务器大量的时间。

      在您运行测试时运行mongostat,它可以告诉您很多信息(运行mongostat --discover | grep -v SEC 以查看所有分片主控的指标,如果您的mongos,请不要忘记包含--port没有在 27017 上运行)。


      解决您更新中的问题:如果 Mongo 确实将块物理上保持在一起,那将是非常好的,但事实并非如此。原因之一是分片是mongod 之上的一层,而mongod 并没有完全意识到它是一个分片。知道分片键和存在哪些块的是配置服务器和mongos 进程。因此,在当前架构中,mongod 甚至没有将块保存在磁盘上所需的信息。问题更严重:Mongo 的磁盘格式不是很先进。它仍然(从 v2.0 开始)没有在线压缩(尽管压缩在 v2.0 中变得更好),它不能压缩碎片数据库并仍然提供查询。遗憾的是,Mongo 要实现您的建议还有很长的路要走。

      此时您可以做的最好的事情是确保按顺序写入数据,以便按顺序写入块。如果您也预先创建所有块,这可能会有所帮助,这样数据就不会被平衡器移动。当然,这只有在您事先拥有所有数据的情况下才有可能,而且这似乎不太可能。

      【讨论】:

        猜你喜欢
        • 2011-08-05
        • 2014-07-31
        • 2019-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 1970-01-01
        • 2014-04-06
        相关资源
        最近更新 更多