【发布时间】:2012-07-20 12:44:45
【问题描述】:
我的任务是将数据从 MongoDB 数据库移植到 MySQL 数据库。 (移植有充分的理由 - 所以它必须完成)。
MongoDB 集合:
- 拥有大约 1.1 亿份文档
- 大小为 60 GB
- 具有重要属性的索引
- 正在运行不为任何生产流量提供服务的 Windows 2008 独立独立服务器
我们尝试过的设置:
- 具有 7.5 Gigs RAM / 8 Gigs 页面文件的大型 Amazon EC2 Win2008 服务器实例
- 一个将 MongoDB 数据转换为本地 MySQL 数据库的 C# 控制台应用程序
我们一次从 MongoDB 的内存中提取 1K 个文档,进行必要的处理,然后将它们保存到 MySQL db,一次批量写入 500 个。
我们面临的问题是,每 250 万个文档,服务器就会阻塞,Mongo 响应非常缓慢 - 应用程序的数据获取操作超时(在处理 100 万个文档时,可用 RAM 已满)
我们通过杀死 mongod 进程并在它崩溃时每 250 万条记录重新启动它来缓慢前进 - 但我敢打赌我们做错了什么。
问题:
我是否应该为此将 Mongo 服务器移动到基于 Linux 的大型实例并将 MySQL 移动到 Amazon RDS 并用 PHP 重写转换应用程序?会有帮助吗?
我们决定将它全部放在一个盒子上的原因是在不同的盒子上拥有不同的服务器会导致延迟问题 - 但我想如果盒子窒息的话那是没有实际意义的。
我还可以尝试哪些其他事情/可以使用哪些技巧?
感谢您阅读本文!
-- 更新01--
自从我重新启动我的应用程序并进行了以下更改后大约 6 小时:
- 将 Mongo 读取计数从 1,000 条增加到 10,000 条记录。 .skip(10K).limit(10K)
- 从 MySQL 目标数据库中删除了所有索引。
- 将 Windows 页面大小从 4 Gigs 增加到 8 Gigs
我的内存消耗为 100%,但应用程序仍在运行。 (上次它在 52 分钟内发出呱呱叫声)。 Mongo 吃 6.8 Gigs 的 RAM,MySQL - 450 Megs 和转换器应用程序 - 400 Megs(大约值)。
到目前为止处理了 1100 万条记录 - 但速度已经从大约 500 条记录/秒下降到 370 条记录/秒。
接下来的步骤是将 Mongo 和 MySQL 服务器隔离到单独的盒子中,并将它们都保持在同一个 Amazon 可用区中以最大程度地减少延迟。
-- 更新 02 --
我们对代码进行了一些更改以使用 Mongo 光标并让它自动递增,而不是自己执行 .skip().limt()。这大大加快了这个过程,我们每秒可以处理 1250 条记录,而之前的记录是 300 多条。但是,应用程序开始消耗过多的内存,并且会耗尽 RAM 并崩溃,并且需要在每 2M 条记录后重新启动。
我们使用了这个代码sn-p:
var docs = db[collectionName].Find(query);
docs.SetBatchSize(numOfResultsToFetchAtATime);
foreach (var d in docs) {
// do processing
}
所以它的作用是一次获取 'numOfResultsToFetchAtATime' 记录 - 但随后在循环中自动进行并获取下一组记录。 Mongo 使用 Cursor 处理这一进程,因此速度要快得多。
但是,我们仍然无法成功移植它。 当这种情况发生时,我会用代码发布我的回复。
-- 更新 03:成功--
我们最终使用了@scarpacci 的建议来做一个 mongoexport。 请记住,mongodb 必须位于 linux 机器上而不是 windows 机器上。
我们首先尝试在本地 MongoDB 上从 Windows 执行 mongoexport,无论我们尝试什么,对于一个大型集合 (13Gigs+),它都会在不同的地方失败
最后,我在 Linux 机器上恢复了数据库,mongoexport 就像一个魅力一样工作。
没有 Json -> MySQL 转换器 - 所以我们不得不做很多事情。 稍作调整,我们就可以使用我们以前的应用程序并读取文件并直接写入 MySQL。它快速且相对没有错误。
我们在处理大文件时遇到了一些问题,但是将 13GB 文件分解为 500 Meg 长的文件有助于解决这个问题,并且我们能够成功地将所有数据迁移到 MySQL。
非常感谢大家花时间帮助我们。希望这个解释对将来的人有所帮助。
【问题讨论】:
-
索引呢,没事吧?
-
我认为将应用程序和 mysql 移动到不同的服务器可能会有所帮助。 Mongo 喜欢独处,因此它可以消耗所有可用的 RAM。如果迁移中未使用索引,您可能会考虑删除它们。或者,您可以尝试将 mysql 配置为具有非常低的最大 RAM,并确保 C# 应用程序没有增加其内存使用量。
-
你为什么要切换到MySql?只是好奇....想知道 MongoDB 的推理/问题...谢谢--S
-
我没有使用过 MongoDB,而且我已经有好几年没有使用过 MySQL 了,但是,我将竭尽全力将矛头指向您的控制台应用程序。我之前制作过 C# 控制台应用程序来做同样的事情,但记录的数量较少(数千,而不是数百万)。我一直看到控制台应用程序在获取数据时会增长[在内存中]。我不在乎,因为无论如何它很快就完成了,但是您可能想投资重写控制台应用程序,并且绝对确保您正在清理它的内存使用量,因为它正在执行它的任务。
-
@scarpacci:这是一个分析数据库,早期的开发人员选择在 Mongo 上做,因为当时数据不是很重要。一种快速火和肮脏的方法。突然间,我们的应用程序(它是一个 iPhone 应用程序)起飞了,我们拥有了难以查询的海量数据。索引不再有太大帮助,并且 map-reducers 需要花费大量时间来获取我们需要的报告。因此,我们正在尝试将数据移动到一个完全非规范化(无外键)的 MySQL 实例。
标签: c# mysql mongodb windows-server-2008 mongodb-.net-driver