PHP脚本超出了数据库SELECT的内存限制

时间:2016-01-14 19:08:12

标签: php mysql

我指的是这段代码,我一直在写:

https://github.com/sharedRoutine/PHP-Scripts/blob/master/class.dbmanager.php#L295

当我打开网站时,此行正在登录error.log。它加载了大量数据(超过120k)条目。

所以经常调用mysqli_stmt_fetch。对于每个条目,将创建一个对象并将其推送到数组上。

我可以做些什么来优化这段代码?减少使用内存。我知道有增加内存的方法,也有克隆,但我不能使用它,因为我每次调用mysqli_stmt_fetch都会设置$ row属性,这些属性通过引用传递。

或者,对于此调用,我可以使用COUNT语句而不是SELECT,但是我正在尝试修复可能的内存泄漏。

即使这段代码也存在同样的问题:

while (mysqli_stmt_fetch($prep)) {
    $obj = new stdClass();
    foreach ($info as $key => $value) {
        $obj->$value = $row->$value;
    }
    array_push($resultArray,$obj);
    unset($obj); //unset the object
}

任何想法都表示赞赏。

  • xCoder(sharedRoutine)

3 个答案:

答案 0 :(得分:0)

如果你确实需要它们全部存储在内存中并且不能同时获得更少的条目,那么你可以做的最后一种方法是在数组中存储每个对象的序列化+压缩字符串,然后根据需要反序列化+解压缩。

请参阅http://php.net/zlibhttp://php.net/serialize

作为提示,如果你压缩了一系列序列化对象(比如每个子对象有100个对象的子阵列,并且每个子阵列都被序列化和压缩),那么可以节省更多的内存。

我不主张将其作为推荐方法,因为它会引入复杂性并使用额外的CPU来压缩/解压缩,但如果您没有其他选择并且必须将它们保留在内存中,那么这是一种可能的解决方案

答案 1 :(得分:0)

您可以使用generators。优点是它们产生每个元素而不是将它们全部写入系统内存。

function my_object_generator($prep) {
    while ($info=mysqli_stmt_fetch($prep)) {
        $obj = new stdClass();
        foreach ($info as $key => $value) {
            $obj->$value = $row->$value;
        }
        yield $obj;
    }
}

$read_transformed_data = my_object_generator($prep);
foreach ($foo in $read_transformed_data) {
   print($foo);
}

一个优点是您不需要以块的形式处理数据。 一个缺点是您无法计算数据的长度。但是对于繁重的数据集,应该使用mysql计数函数来实现此目的。另请注意,您不会再次将生成器输出收集到另一个阵列中。这将导致与以前相同的问题。

答案 2 :(得分:-1)

使用PDO代替mysqli并执行此操作:

$result = $query->fetchAll(PDO::FETCH_OBJ);

为您提供一个对象数组,其列名为键(db值为值)。 非常整洁..不需要循环