Php 以更高效的内存方式操作大数组

Php 以更高效的内存方式操作大数组,php,arrays,memory,memory-limit,Php,Arrays,Memory,Memory Limit,我目前正在为一个应用程序编写一个API,该应用程序与一个大型数据库接口,需要从中检索大量数据,然后将其作为JSON输出 我使用CodeIgniter(CI)作为数据库接口,但我认为这与此无关。我遇到了内存限制,不幸的是,我没有办法增加内存限制,因为共享主机服务无法做到这一点 我从数据库中得到大约56k行,这些行通过CI(零索引,相当标准)放入一个数组中。每行有7个字段 在我开始通过数组循环修改数据之前,一切都很好。即使我只是修改原始数组,而不是分配新的变量,脚本在经过几次循环迭代后仍会遇到内存限

我目前正在为一个应用程序编写一个API,该应用程序与一个大型数据库接口,需要从中检索大量数据,然后将其作为JSON输出

我使用CodeIgniter(CI)作为数据库接口,但我认为这与此无关。我遇到了内存限制,不幸的是,我没有办法增加内存限制,因为共享主机服务无法做到这一点

我从数据库中得到大约56k行,这些行通过CI(零索引,相当标准)放入一个数组中。每行有7个字段

在我开始通过数组循环修改数据之前,一切都很好。即使我只是修改原始数组,而不是分配新的变量,脚本在经过几次循环迭代后仍会遇到内存限制错误

Allowed memory size of 134217728 bytes exhausted
下面是我正在使用的代码:

$query = $this->db->get('table');
if ($query->num_rows() > 0) {
    $result = $query->result_array();
    foreach ($result as $k => $v) {
        foreach($v as $key => $value) {
            if ($key === 'column_name') {
                $result[$k][$key] = json_decode($value);
                continue;
            }
            if ($value == null) {
                $result[$k][$key] = '';
            } else if (ctype_digit($value)) {
                $result[$k][$key] = (int) $result[$k][$key];
            }
        }
    }
    return $result;
}
只是解码一些json并转换成整数或空字符串,没什么特别的。但是我会在任何一行中得到内存限制错误,这会改变
$result
数组。即使我删除了(内存密集型)
json\u decode
,我仍然会在第行得到一个错误,该错误只会转换为
int

更重要的是,即使我删除了整个
foreach
,我在稍后使用
json\u encode
生成API响应时也会出现内存限制错误

我完全迷路了,我真的需要一次输出这么多的数据,不知道如何提高内存效率(可能是使用类似缓冲区之类的东西?从未涉足过)

编辑:对于任何感兴趣的人,我通过对数据库进行无缓冲查询,设法在一定程度上减少了内存使用。这样,阵列中只存储1个数据副本。我还删除了foreach并专门处理每个字段。然而,主要问题可能是如何解决。以下是新代码:

$query = $this->db->get('table');
$result = [];
while ($row = $query->unbuffered_row('array')) {
    if ($row['column1'] == '[]') {
        $row['column1'] = [];
    } else {
        $row['column1'] = json_decode($row['column1']);
    }
    $row['column2'] = (int) $row['column2'];
    $row['column3'] = (int) $row['column3'];
    $row['column4'] = is_null($row['column4']) ? '' : (int) $row['column4'];
    $row['column5'] = is_null($row['column5']) ? '' : (int) $row['column5'];

    $result[] = $row;
}

return $result;

有很多方法可以解决这个问题,真正的问题是你的优先事项是什么

  • 一定要快吗?会慢吗
  • 内存不足的服务器是唯一可用的资源吗
理想的解决方案显然是升级您的服务器,假设您有消耗大量内存的任务,这应该是运行此项目的人关心的问题

显然,有一种现代的方式可以使用微服务来完成,每个微服务处理一大块数据。它们可以由您编写,也可以使用AWS等云服务


话虽如此,假设您确实限于当前的星座,并且除了使用有限的内存服务器来处理大数据之外,您没有其他选择,我建议您使用本地文件I/O—这不是最快的解决方案,但是,如果您读取数据块并不断将其写入临时文件,您将保存内存问题,然后可以将该文件刷新到客户端。

什么是PHP内存限制设置?@user2182349错误消息指出
允许的内存大小134217728字节已用尽
。将此添加到问题中。谢谢。将其加倍-您应该很好
Foreach
复制它所覆盖的数组。或者使用
for
do。。。而
loop@Michel谢谢,我怀疑类似的事情。我读到绝对不建议使用foreach引用赋值,所以我可能会进行简单循环。但是是的,我的内存量有点可疑,我需要联系主机提供商。谢谢你的回答。我确实受到这台服务器的限制,我希望他们把事情搞砸了,服务器应该有更多的内存,但我要到明天支持恢复时才能确定。我可以研究云服务,那将是一次有趣的经历。文件IO可能不是一个选项,因为这必须有点快,但我会做一个测试来确定。谢谢如果他们想让它更快,他们应该给你更多的资源,至少控制php.ini:)祝你好运!顺便说一句,我不确定您的服务器客户端是如何设置的,但是如果这个查询是使用API调用完成的,您可以尝试简单地继续输出数据(echo),而不是将其存储在一个数组中,这可能行得通。另一个解决方法是使用EventSource,这是一种web套接字,可以保持客户端和服务器之间的连接(需要html5)是的,我完全同意,我收到老板的电子邮件,要求他们升级到专用服务器。回显数据的想法还不错,但我需要输出json,因此需要做一些工作来确保所有内容都正确格式化,而且这并不能保证我能够在内存中保存完整的数据库结果,在这种情况下,我必须执行一些无缓冲的mysql请求。目前,我设法对API发出了几个请求,而不是一个请求,但这并不理想。