【问题标题】:Memory problems while copying data from one mysql table to another将数据从一个mysql表复制到另一个表时出现内存问题
【发布时间】:2013-06-01 14:33:37
【问题描述】:

我需要获取、转换然后将 4 000 000 行插入到另一个表中。 不用说,在 300 000~ 个条目后会出现内存耗尽错误。在每个循环分配的内存之后恰好增加 160 字节。 我知道使用 mysql_unbuffered_query() 是可能的,尽管它迫使我在执行另一个查询之前获取所有结果行,这最终导致内存耗尽错误再次出现。那么,单次运行的最佳方法是什么?

mysql_connect($host, $user, $password);
mysql_select_db($db);

$getOldData = mysql_query("
SELECT *
FROM players_online 
ORDER by id ASC
");
$numRows = mysql_num_rows($getOldData);

for ($i=0; $i < $numRows; $i++) { 
$oldData = mysql_fetch_assoc($getOldData);
$hour = explode(':', $oldData['hour']);
$quarters = $hour[0] * 4 + $hour[1] / 15;

$update = mysql_query("
    INSERT INTO players_online_2 (world_id, players_online, quarters_past_midnight, date)
    VALUES (
        '".$oldData['world_id']."', 
        '".$oldData['players_online']."', 
        '".$quarters."', 
        '".$oldData['date']."'
    )
    ON DUPLICATE KEY UPDATE
        world_id='".$oldData['world_id']."', 
        players_online='".$oldData['players_online']."', 
        quarters_past_midnight='".$quarters."', 
        date='".$oldData['date']."'
");

if (mysql_error()) {
    echo mysql_error();
    die();
}

echo memory_get_usage().PHP_EOL;

}

【问题讨论】:

  • 有什么理由不直接在数据库中做呢?
  • 中间需要进行一些转换。
  • 由于您似乎正在做的唯一数据转换是较小的日期/时间更改,您仍然可以将其作为 INSERT INTO... SELECT FROM 直接在数据库上进行

标签: php mysql memory


【解决方案1】:

MySQL Workbench 将让您将export 旧数据库和import 放入新位置。

话虽如此,但如果您想在 PHP 中执行此操作,您可能不应该一次性返回整个表格。您可以使用LIMITOFFSET 将查询拆分为页面,然后一次执行一页。像这样的:

for ($i = 0; $i < $Limit; $i++)
{
  // SELECT * FROM players_online ORDER by id ASC LIMIT 1000 OFFSET ' . $i
}

【讨论】:

    【解决方案2】:

    您可以在单个查询中执行此操作,例如:

    INSERT INTO players_online_2 (world_id, players_online, quarters_past_midnight, date)
        select world_id, players_online, quarters_past_midnight, date
        FROM players_online po
        ORDER by id ASC
    ON DUPLICATE KEY UPDATE
        world_id = po.world_id,
        players_online = po.players_online, 
        quarters_past_midnight = po.quarters_past_midnight, 
        date = po.date;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-20
      相关资源
      最近更新 更多