大型SQL结果集占用太多内存 - CodeIgniter

时间:2012-01-10 23:05:52

标签: php mysql sql codeigniter

我使用CodeIgniter发出一个SQL查询,它可以返回超过80,000行作为结果。每行有三列,所有列都是整数,我收到一个PHP错误: 致命错误:允许的内存大小为134217728字节耗尽

似乎我尝试使用超过128MB的数据从MySQL服务器检索结果。我使用$ query-> result_array()来检索结果。我得到的结果显然在空间方面存在严重的开销。假设我检索100,000行,包含3个整数。所以100,000 *((3 * 4 + 10)= 2.1MB。(10是用于列id等的字节数)。

我做错了吗?

----------------------解决----------------------- < / p>

通过修改CodeIgniter代码解决:link

现在执行速度更快,脚本只需要大约3MB内存,而不是128MB。

5 个答案:

答案 0 :(得分:2)

我不确定CI究竟如何返回结果,但您绝对不希望将整个数据集放在一个数组中。为什么不根据需要遍历每一行?

<?php

$result = $this->db->query('SELECT ...');
while($row = $result->next_row())
{
  // do something with that single row
}

答案 1 :(得分:1)

除非你真的需要检索所有记录 - 例如出口或批次目的 - 我强烈建议始终查询块

MySQL's SELECT statement has this option

[LIMIT {[offset,] row_count | row_count OFFSET offset}]

例如

Limit 10, 200

提供以记录10开头的200条记录

答案 2 :(得分:1)

如果要向页面显示结果,则很可能需要使用分页。如果您正在对数据执行操作,那么您将需要使用LIMITS和OFFSETS分段执行操作。否则你需要增加内存限制,我不建议大于128MB。

答案 3 :(得分:0)

即使问题得到解答,3MB仍然很多。你真的需要将它全部存储在内存中吗?正常的PHP占用空间大约为1MB或更少,因为它在编程时考虑了内存。您甚至可能达到8MB以上的事实是非常令人不安的,并且在具有数千次页面命中的真实生产环境中,您的服务器将崩溃并烧毁。我强烈建议您修改代码。

答案 4 :(得分:0)

我遇到了与CI相同的问题。不幸的是,修改DB后端对我来说不是一个选择。所以我的解决方案是在模型中使用mysqli_函数并自己遍历每个记录:

$result = mysqli_query($sql);
while ($row = mysqli_fetch_assoc($result)){
    // process batch
}

以这种方式处理记录,我没有必要进行sql分页,也没有将所有信息存储在1个数组中。这也适用于mysql_函数(取决于您使用的数据库驱动程序)。这里的缺点是:

  • 您没有使用CI数据库引擎,因此如果您决定使用其他驱动程序,则必须手动更新这些查询。
  • 除非您以某种方式存储数据库标识符,否则不会使用多个数据库。

可能还有其他一些缺点,但对我来说它有效并且不会消耗那么多数据。