【发布时间】:2017-12-13 06:55:18
【问题描述】:
我目前正在为一个与大型数据库交互的应用编写 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_decode,我仍然会在线收到一个错误,该错误会简单地转换为int。
更重要的是,即使我删除了整个foreach,稍后当我使用json_encode 生成API 响应时,我也会遇到内存限制错误。
我完全迷失了,我真的需要一次输出这么多的数据,不知道如何提高内存效率(可能有类似缓冲区之类的东西?从来没有深入研究过)。
编辑:对于任何感兴趣的人,我设法通过对数据库进行无缓冲查询来减少内存使用量。这样,只有 1 个数据副本存储在数组中。我还删除了 foreach 并专门处理每个字段。然而,主要问题可能是PHP stores arrays.这是新代码:
$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;
【问题讨论】:
-
什么是 PHP 内存限制设置?
-
@user2182349 错误消息指出
Allowed memory size of 134217728 bytes exhausted。将其添加到问题中谢谢。 -
加倍 - 你应该没问题
-
Foreach复制它迭代的数组。 Manual: In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.。或使用for或do... while循环 -
@Michel 谢谢,我怀疑有类似的事情。我读到绝对不建议在 foreach 中使用引用赋值,所以我可能会进行简单的循环。但是,是的,我的内存量有些可疑,我需要联系托管服务提供商。
标签: php arrays memory memory-limit