【问题标题】:Archiving mysql data throwing memory limit issue归档mysql数据抛出内存限制问题
【发布时间】:2015-04-11 20:14:26
【问题描述】:

我有多个表。比如table1、table2、table3等

需要什么
1. 从 table1 中获取特定行。 (例如:id = 203)
2.从table2中获取所有与id 203相关的值(例如:1,2,3,4,5,6,7....500)
3. 再次从 table3、table4 等中获取步骤 2 中与 table2 具有外键关系的所有 id 值。(数百万行)
4. 根据结果为以上 3 个步骤构建插入语句。
5. 在存档数据库中具有相同表名的受尊重表中插入步骤 4 的查询。即,简而言之,将部分数据归档到归档数据库中。

我的表现如何
对于每个表,每当获得行时,创建插入语句并存储在每个表的特定数组中。一旦获取所有值直到第 3 步,创建插入语句并存储在数组中。然后为每个单独的数组运行循环并执行这些查询存档数据库。一旦查询成功执行,从主数据库中删除所有获取的行,然后提交事务。

结果
到目前为止,上述方法对于 10-20mb 左右的小型 DB 数据非常有效。

问题
对于大量行(比如超过 5gb),php 在获取行时抛出内存耗尽错误,因此无法在生产中工作。即使我已经将内存限制增加到 3gb。我不想再增加了。

我正在考虑的替代解决方案是,而不是使用数组来存储查询,将这些查询存储在文件中,然后在内部使用 infile 命令执行查询以存档 DB。

请建议如何实现上述问题?移至存档数据库后,需要移回具有类似功能的主数据库。

【问题讨论】:

    标签: php mysql arrays out-of-memory archive


    【解决方案1】:

    处理大型结果集有两个关键。

    第一个是逐行流式传输结果集。除非您明确指定,否则 MySQL 的 php API 会立即尝试将整个结果集从 MySQL 服务器读取到客户端内存中,然后逐行导航。如果你的结果集有数万或数十万行,这会导致 php 内存不足。

    如果您使用mysql_ 接口,请使用mysql_unbuffered_query()。不过,您不应该使用该界面。它已被弃用,因为它很糟糕。

    如果您使用mysqli_ 接口,请调用mysqli_real_query() 而不是mysqli_query()。然后调用mysqli_use_result() 开始检索结果集。然后,您可以使用one of the fetch() variants 获取每一行。获取所有行后,不要忘记使用mysqli_free_result() 关闭结果集。 mysqli_ 有面向对象的方法;你也可以使用它们。

    PDO 具有从服务器到客户端的流式传输结果集的类似方式。

    处理大型结果集的第二个关键是使用第二个连接到您的 MySQL 服务器来执行 INSERTUPDATE 操作,这样您就不必在内存中累积它们。如果您选择将信息写入文件系统中的文件,也是如此:一次写入一行,这样您就不必将其保存在 RAM 中。

    诀窍是一次处理一行或几行,而不是数万行。

    不得不说:许多人更喜欢使用用 Java、C# 或 PERL 等数字运算语言编写的命令行程序来进行此类数据库维护。

    【讨论】:

    • 谢谢奥利琼斯。我正在使用 mysqli 接口。但是,是的,使用 mysqli_query() 函数进行查询。将尝试使用您建议的功能并查看它是否有效。我还将使用 mysqli_free_result 函数来释放使用的内存。我使用 php 的原因是因为整个应用程序仅在 PHP 中。而且这个归档过程也是应用程序的一部分。我猜是在 php 数组中存储行时,它会消耗更多的内存。
    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    相关资源
    最近更新 更多