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


PHP Script exceeds memory limit for database SELECT

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

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

当我打开网站时.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)

如果您确实需要将它们全部存储在内存中并且不能一次获得较少的条目,那么作为最后的手段,您可以在数组中存储每个对象的序列化+压缩字符串,然后根据需要反序列化+解压缩。

查看 http://php.net/zlib 和 http://php.net/serialize

作为提示,如果您压缩序列化对象

组(例如每个子数组包含 100 个对象,并且序列化+压缩每个子数组),则可以节省更大的内存。

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

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

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计数函数来实现此目的。另请注意,不要再次将生成器输出收集到另一个数组中。这将导致与以前相同的问题。

使用 PDO 而不是 mysqli 并执行以下操作:

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

为您提供一个对象数组,其中列名作为键(db 值作为值)。相当整洁..无需 while 循环