【问题标题】:Switch from Mysql to MongoDB 200 millions rows从Mysql切换到MongoDB 2亿行
【发布时间】:2011-10-13 13:22:42
【问题描述】:

我们正在尝试从 mysql 迁移到 mongodb。 mysql结构是 id_src 整数 id_dest int 唯一键:id_src,id_dest

它们在 mysql 中大约有 2 亿行

数据示例: {id_src,id_dest} {1,2} {1,3} {1,10} {2,3} {2,10} {4,3}

我们需要检索数据: {id_dest,count} {3,3} {10,2} {2,1}

我开始在mongodb中重现mysql的结构。 插入性能非常好(非常好):插入 2 亿行大约需要 1 小时。

但我需要使用 map reduce 来获取分组。 Map reduce 大约需要 1 小时。

所以我尝试创建另一个 mongodb 结构: {id_dest,{id_src1,id_src2}}

每个文档可以有十万个id_src。

这是我的 insert.php 代码

$res=mysql_unbuffered_query("select * from ids limit 10000100");  
while ($tab=mysql_fetch_array($res)) {  
$collection->update(array('_id'=>(int)$tab['id_dest']),array('$push' => array('src'=>(int)$tab['id_src'])),array("upsert" => true));  
}  

但在那种情况下性能很差,每秒只有很少的更新。

我做错了吗?

【问题讨论】:

  • 如果 1h 对于 200m 行来说是“巨大的”,那么让我问你这个问题:在 MySQL 中插入 200m 行需要多长时间?
  • 当我说“巨大”时,我是在说“非常非常好”。但是我的问题是地图减少了获得“分组依据”的时间,这对我们来说是可以接受但并不完美的。我想知道使用 mongodb 特性(多值字段)的新文档模型是否比仅仅重现 mysql 数据结构不聪明。
  • 我明白了。让我们等待一个好的答案,然后:-)
  • 感谢 @lukas 帮助我理解我的观点
  • Mongo 中的 MapReduce 目前有一个主要的“缺点”:它目前只使用一个 cpu...

标签: mysql mongodb bigdata


【解决方案1】:

首先,Map/Reduce 不是为实时分析而设计的。此外,MongoDB 目前仅限于一个内核用于 M/R,这将进一步减慢速度。

因此,如果您要使用 M/R 获取数据,它不会是“实时的”,它会每 X 分钟(或几小时)更新一次。

这里有两种有效的方法:

  1. 增量 M/R
  2. 实时计数器

选项 #1:增量 M/R

对于此选项,您对所有数据运行一次 M/R。然后,继续前进,您只对修改后的数据运行 M/R。如果你现在有 200M 个文档,那么接下来可能有 210M 个文档(这意味着 M/R 变得更慢)。但是,如果您只需要运行新的/更改的文档,那么它应该花费不到 1 小时。

查看文档here 中的reduce 输出选项。

同样的前提是您只 M/R 相关数据和系统对现有数据“重新减少”。通过这种方式,您可以获得“增量”M/R。

选项 #2:实时计数器

在这种方法中,您有两个集合:一个用于您的数据,另一个用于“摘要”的结果。插入数据时,还会对摘要进行增量。

假设你有这个数据:

Main Collection
{src: 1, dest: 2}
{src: 1, dest: 3}
{src: 1, dest: 10}
{src: 2, dest: 3}
{src: 2, dest: 10}
{src: 4, dest: 3}

Summary Collection
{dest: 3, count: 3}
{dest: 10, count: 2}
{dest: 2, count: 1}

您收到一条新数据{src: 5, dest: 2}。你会做两个更新:

db.main.insert({src: 5, dest: 2});
db.summary.update({dest: 2}, { $inc : { count: 1 } }, true); // upsert true

这是您的新数据:

Main Collection
{src: 1, dest: 2}
...
{src: 4, dest: 3}
{src: 5, dest: 2}

Summary Collection
{dest: 3, count: 3}
{dest: 10, count: 2}
{dest: 2, count: 2}

您会注意到我们更新了摘要:{dest: 2, count: 2}

显然,这里需要权衡取舍。您需要更多更新/插入 (2x),但您会获得实时计数器。现在,MongoDB 中没有事务,因此您必须决定确保两个更新都发生的策略。有很多方法可以做到这一点,我在这里无法介绍(请参阅消息队列了解一种方法)。

【讨论】:

  • 我在过去几个小时内实施了您建议的实时解决方案。我只是得到很好的结果。更新摘要集合非常快,几乎不会降低性能,而且我得到了实时更新计数器。谢谢!
猜你喜欢
  • 2012-12-14
  • 1970-01-01
  • 2014-01-29
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 2011-10-18
  • 1970-01-01
相关资源
最近更新 更多