【发布时间】:2015-08-28 13:13:33
【问题描述】:
我有一个 Cronjob 脚本,用 PHP 编写,具有以下要求:
- 第 1 步(数据库服务器 1): 从多个表中获取一些数据(我们这里有很多数据)
- 第 2 步(应用服务器):执行一些计算
- 第 3 步(数据库服务器 2): 计算后,将该数据插入另一个数据库(MySQL)/表(InnoDB)以进行报告。该表包含 97 列,实际上是不同的比率,无法进一步标准化。这是不同的物理数据库服务器,只有一个数据库。
脚本在开发过程中运行良好,但在生产过程中,第 1 步返回了大约 5000 万条记录。结果,很明显,脚本运行了大约 4 天,然后失败了。 (粗略估计,以目前的速度,大约需要 171 天才能完成)
请注意,我们使用的是准备好的语句,第 1 步是一次获取 1000 条记录中的数据。
到目前为止我们做了什么
优化步骤1:插入和删除所有索引中的多个值
一些测试显示插入(上面的第 3 步)花费了最长的时间(超过 95% 的时间)。为了优化,经过一番谷歌搜索,我们从表中删除了所有索引,而不是一个插入查询/行,我们没有一个插入查询/100 行。这给了我们更快的插入速度,但根据粗略估计,运行一次 cron 需要 90 天,而且我们需要每个月运行一次,因为每个月都会有新数据可用。
优化步骤2,不写DB,写csv文件,然后用linux命令导入mysql。
这一步似乎不起作用。在 CSV 文件中写入 30000 行需要 16 分钟,我们仍然需要在 MySQL 中导入该 CSV 文件。我们为所有写入操作提供了单个文件处理程序。
当前状态
我现在似乎不知道还能做什么。一些关键要求:
- 脚本需要插入大约 50,000,000 条记录(会随着时间增加)
- 每条记录有 97 列,我们可以跳过一些,但至少 85 列。
- 根据输入,我们可以将脚本分成三个不同的 cron 以在三个不同的服务器上运行,但插入必须在一个数据库服务器(主服务器)上完成,因此不确定它是否会有所帮助。
但是:
- 我们愿意更改数据库/存储引擎(包括 NoSQL)
- 在生产环境中,我们可以有多个数据库服务器,但插入只能在主服务器上完成。所有读取操作都可以定向到从属,这是最小的和偶尔的(只是为了生成报告)
问题
我不需要任何描述性的答案,但简而言之,有人可以提出可能的解决方案。我只需要一些优化提示,我会做剩余的研发。
我们对一切都开放,更改数据库/存储引擎、服务器优化/多台服务器(数据库和应用程序)、更改编程语言或任何满足上述要求的最佳配置。
最终预期,cron 必须在最多 24 小时内完成。
在优化步骤 2 中编辑
为了进一步了解生成 csv 需要时间的原因,我创建了我的代码的副本,其中仅包含必要的代码。该代码存在于 git https://github.com/kapilsharma/xz
实验输出文件为https://github.com/kapilsharma/xz/blob/master/csv/output500000_batch5000.txt
如果你检查上面的文件,我一次插入 500000 条记录并从数据库中获取 5000 条记录,使循环运行 100 次。第一个循环花费的时间是 0.25982284545898 秒,但第 100 个循环是 3.9140808582306。我假设它是因为系统资源和/或 csv 文件的文件大小。在这种情况下,它变成了更多的编程问题,然后是数据库优化。不过,有人可以提出为什么在下一个循环中需要更多时间吗?
如果需要,除了生成虚拟数据库的 csv 文件和 sql 文件之外的整个代码都会提交,因为这些文件非常大。然而,它们可以很容易地用代码生成。
【问题讨论】:
-
什么实际上不适用于 csv 方法? LOAD DATA INFILE 查询只是失败还是仍然太慢?我了解在您的情况下生成 csv 需要时间。但这种方法通常会大大促进批量插入
-
感谢@Mat 的回复。 30000 条记录耗时 16 分钟。以同样的速度,50000000 条记录将需要 18.5 天,这也仅用于写入 CSV 文件。这就是为什么我没有在这条路上尝试太多。您认为这是给定场景中的最佳解决方案吗?有没有机会在 24 小时内获得整个 cron?
-
首先,让我们关注 30K CSV 行花费了这么长时间。只是
LOAD DATA语句需要 16 分钟吗?或者您是否包括创建 30K 行?请提供SHOW CREATE TABLE。 (由此,我们也可以进一步讨论索引。)服务器 2 上的SHOW VARIABLES LIKE '%buffer%';。 -
感谢@RickJames,我用代码更新了问题,并在一次使用虚拟记录的实验中得到了结果。
-
时间线性增长,好像第一个测试做了 N 行,第二个做了 2N 行,第三个做了 3N 行,等等。我没有发现构建行数以确认或拒绝的代码那个观察。
标签: php mysql optimization query-optimization innodb