【问题标题】:PHP: how are query results stored in mysqli_resultPHP:查询结果如何存储在 mysqli_result 中
【发布时间】:2012-07-27 05:29:47
【问题描述】:

当我对数据库进行查询并在 mysqli_result 中检索结果时,内存使用量非常小。但是,当我将查询结果中的所有行提取到关联数组中时,内存使用率会变得非常高。

<?php
    require_once("../config.php"); //db connection config
    $db = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_DBASE);

    $query ="select * from table_name";
    if($r = $db->query($query)){
    echo "MEMORY USAGE before :  ". memory_get_usage()."<br><br>";
    $rows = array();
    while($row = $r->fetch_assoc()){

        $rows[]= $row;
    }
    echo "MEMORY USAGE after :  ". memory_get_usage()."<br><br>";


    //before: 660880
    //after:  114655768
    // # of records: around 30 thousands
?>

对我来说存储这么多结果非常消耗内存是有道理的,但我只是想知道 mysqli_result 怎么会这么小。不可能每次调用 fetch_assoc 时都向 dbase 查询结果。那么结果在内存中存储在哪里。

【问题讨论】:

  • 我在某处读到mysql_* 函数一次从服务器获取所有结果行。但是 PDO(可能还有 mysqli)按需检索每一行。因此,每次调用 fetch 时,都会消耗一点内存。但是您将每一行存储在一个数组中,因此您的内存使用量会累积是有道理的。
  • 你的意思是每次调用fetch,mysqli都会查询数据库的结果吗?
  • 据我了解,当您调用query() 时,MySQL 会执行查询并准备将所有结果行返回给 PHP。但是,如果 mysqli 类似于 PDO(至少是 PDO 的默认值),那么在您调用 fetch 之前它不会开始接收行。除非您调用fetchAll(),否则将一次检索每一行。这意味着您的内存使用是因为您将结果保存在数组中,而不是因为 mysqli。
  • 您可能想查看free()。我认为您的阵列存储会影响结果。在调用free() 后也尝试测量内存使用情况。然后可以观察mysqli实际使用了多少内存。

标签: php memory mysqli


【解决方案1】:

获取结果和存储指向资源的指针之间存在巨大差异。

如果你在第一次调用memory_get_usage(); 之前echo $r;,你会意识到它只是一个指针。这是指向您的结果集的指针。在您fetch您的结果之前,结果集实际上不会存储到内存中。

我建议您运行 fetchAll() 来完成您想要做的事情。这将导致 1 种方法以更好的性能访问所有结果,因为它是在 mysqli 扩展(C 库)而不是 PHP 中的循环上产生的。

您还可以在使用完结果后使用免费结果功能从内存中清除结果。如果您熟悉的话,这就像在 Java 中关闭游标一样。

【讨论】:

  • 谢谢。这很有帮助! :)
  • 那么,为什么资源实际上并没有添加到内存使用中呢?该资源正在使用内存空间......或者它是写入磁盘还是什么?
  • 通过在调用 fetch 之前回显$r,MySQL 会为查询结果分配空间,而不是 PHP。 PHP 只会在你调用 fetch 时将结果分配给它的内存空间。
【解决方案2】:

我认为你应该这样做:

while($row = $r->fetch_assoc()){
   //Do whatever you need with the record, then:
   unset($row);
}

您发布的方式是在 $rows 中收集一个巨大的数组,内存使用情况反映了这一点。

【讨论】:

  • 我知道你的意思,这绝对是 fetch_assoc() 的初衷。问题是我要获取结果并对其进行处理并将其传递给视图(在 MVC 意义上)以显示记录。我想我可以更改我的实现,以便一次将一条记录传递给查看。
  • 谢谢。这是一个问题,因为我一直在努力避免让视图直接与模型通信,所以我在两者之间还有一个控制器来传递数据。然后我需要做的是创建非常小的视图模板来显示每条记录...
  • @spchuang 如果您有大约 30k 条记录,您似乎应该实现某种分页。无论是使用分页链接还是无休止的页面解决方案。另外,根据我对 MVC 模式的理解,视图不应该与模型通信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2012-11-05
  • 2021-12-28
  • 2021-11-09
  • 1970-01-01
  • 2021-10-11
  • 2017-12-15
相关资源
最近更新 更多