PHP - 处理大型数据集时超过允许的内存

时间:2017-11-06 15:46:04

标签: php out-of-memory bigdata

我有 999,000条记录的列表数据。

我有一个select查询和一个while循环来获取数据,我使用array_push将循环中检索到的值添加到一个数组中。

然后我想要它,所以每个循环处理这个数组中的1000个值。

我的问题是当使用array_push大数据时我收到错误:

Fatal Error: Allowed Memory Size of 134217728 Bytes

如何优化代码以解决我的问题?

我的代码如下:

 $sql = "select customer_id";
 $sql .= " from";
 $sql .= "  t_customer t1";
 $sql .= "  inner join t_mail_address t2 using(mid, customer_id)";
 $result = $conn->query($sql);
 $customerArray = array();
 while ($row = $result ->fetch(PDO::FETCH_ASSOC)) {
    array_push($customerArray , $row);
 }
 // Execute every 1000 record 
 foreach(array_chunk($customerArray , 1000) as $execCustomerArray ) { 
   // My code to execute for every records.
   // ....
 }

2 个答案:

答案 0 :(得分:1)

我不确定它是否可以解决任何问题,但有一件事我会说,你将所有记录推入数组是很愚蠢的。

您正在使用fetch逐个获取它们,然后将它们全部添加到数组中,为什么您只是使用PDOStatement::fetchAll()

示例:

 $sql = "select customer_id";
 $sql .= " from";
 $sql .= "  t_customer t1";
 $sql .= "  inner join t_mail_address t2 using(mid, customer_id)";
 $result = $conn->query($sql);
 $customerArray = $result->fetchAll(PDO::FETCH_ASSOC);
 // Execute every 1000 record 
 foreach(array_chunk($customerArray , 1000) as $execCustomerArray ) { 
   // My code to execute for every records.
   // ....
 }

这可能无法解决您的记忆问题,因为我们无法看到每个客户记录的繁重程度,但我会说,虽然循环你很傻但很可能不是你内存问题的原因

根据这是一个脚本还是一个网页的东西,你也可以有一个增量循环的东西,并使用MySQL LIMIT function to implement basic paging for your data,从而阻止它一次性进入内存,

答案 1 :(得分:0)

如果使用PDOStatement::fetchAll()会占用很多内存,那就不好了。

编辑后的代码如下:

 $sql = "select customer_id";
 $sql .= " from";
 $sql .= "  t_customer t1";
 $sql .= "  inner join t_mail_address t2 using(mid, customer_id)";
 $result = $conn->query($sql);
 $customerArray = array();
 while ($row = $result ->fetch(PDO::FETCH_ASSOC)) {
    array_push($customerArray , $row);

     // Execute every 1000 record 
    if (count($customerArray) == 1000) {
      // My code to execute for every records.
      // ...
      $customerArray = array();
    }
 }

但是如果数组 $ customerArray 存在数据,我不知道如何执行999.000条记录中的最后99条记录。 我不想使用“选择计数”因为表现。