在PHP中,当我们使用mysql_query时,内存中会发生什么

时间:2011-08-31 07:34:24

标签: php mysql memory pointers heap

我曾经使用mysql_query获取大量数据,然后逐个迭代结果来处理数据。例如:

$mysql_result = mysql_query("select * from user");
while($row = mysql_fetch_array($mysql_result)){
    echo $row['email'] . "\n";
}

最近我查看了一些框架并意识到他们将所有数据提取到内存中的数组并返回数组。

$large_array = $db->fetchAll("select * from user");
foreach($large_array as $user){
    echo $user['email'] . "\n";
}

我想知道每种方法的优点/缺点。在我看来,如果你有一个很长的项目列表,将所有内容加载到内存中会导致灾难。但话说回来,一位同事告诉我,无论如何,mysql驱动程序必须将结果集放入内存中。我想得到一个明白问题是关于绩效的人的意见。请不要对代码发表评论,我只是将其作为帖子的一个例子。

由于

4 个答案:

答案 0 :(得分:4)

你正在混合事情。

  • 可用性,使您的代码使用数组更顺畅
  • 和未经优化的算法,当没有经验的程序员倾向于将所有数据加载到脚本中而不是让数据库进行所有计算或分批获取数据时。

因此。框架不会获取所有数据。他们取得了程序员所写的内容 因此,一个优秀的程序员不会将大量数据提取到数组中。在这几个真正需要的情况下,人们会使用旧的逐行提取(并且每个框架都为此提供了一种方法)。在所有其他情况下,应该使用平滑的已经在数组中的提取。

请注意,框架永远不会像在数据库循环内部回显数据那样 每个好的框架都会使用一个模板来输出内容,在这种情况下,一个数组非常方便。

答案 1 :(得分:2)

使用大型结果集时,我通常会批量处理,如下所示:

$current = 0;
$batchSize = 1000;

while (true) {
  $large_array = $db->fetchAll(sprintf("select * from user limit %s, %s", $current, $batchSize));
  if (sizeof($large_array) == 0) {
    break;
  }

  $current += sizeof($large_array);
  foreach($large_array as $user){
    echo $user['email'] . "\n";
  } 
}

只要您的代码没有泄漏内存,您就不必担心哪种方法使用更多内存。在性能方面,在一个查询中加载整个结果集可能会更快,尽管你可能很快会以这种方式达到内存限制,因此性能不再是你的问题了。

顺便说一下,通过设置一个测量两个片段的时间(和峰值内存)的脚本,自己测试它相对容易。我打赌他们的时间不会太大。

答案 2 :(得分:1)

确实,MySQL库“通常”获取客户端内存中的所有数据。它通常使用mysql_store_result()来实现。如上所示,您可以使用LIMIT关键字拆分太大的查询,但存在数据变得不一致的风险,因为它们可能会在两者之间发生变化。你可以使用锁来关心这个。

另一种方法可能是使用mysql_use_result(),它在服务器端使用更多的资源,并且需要尽快完成提取工作。

答案 3 :(得分:-2)

在性能方面我学到的东西:foreachwhile循环更快。也许您应该对每个结果进行基准测试,看看哪个更快,内存更少。恕我直言,我更喜欢后一种方法。但是你真的需要用户表中的每一列吗?如果没有,只需定义您需要的列,而不是使用*来抓取所有列。因为这也有助于记忆和速度。