如何减少 PHP/MySQL 的内存消耗?

Posted

技术标签:

【中文标题】如何减少 PHP/MySQL 的内存消耗?【英文标题】:How to reduce PHP/MySQL memory consumption? 【发布时间】:2019-03-02 09:55:34 【问题描述】:

php 7,mysqli,参考:Example of how to use bind_result vs get_result

我正在使用unbuffered fetching(我希望)并且想知道$m 的内存消耗。当我只是获取(测试用例)时,我希望内存$m 几乎是恒定的。但事实并非如此,这取决于我获取的行数会增加。我希望获取结果的工作方式就像一个游标一次只能获取 1 行。

我将如何实现(一次读取 1 行)?

备注:这里https://***.com/a/14260423/356726他们使用

$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);

但我还没有找到在准备好的语句中传递MYSQLI_USE_RESULT 的方法。

$result = $stmt->get_result(); // not stored I hope
$i = 0;
while ($row = $result->fetch_assoc()) 
    $i++;
    if ($i > 20000) 
        break;
    

$m = memory_get_usage(); // see values between 10-50MB here, depending on i
$this->freeAndCloseStatement($stmt);

【问题讨论】:

如果使用bind_result()fetch()而不是get_result()fetch_assoc(),内存消耗如何? 大小差不多,也不是 const,而是随着获取行的大小而增加。当我释放 SQL 资源(关闭)时,我看到内存急剧下降。意味着结果以某种方式消耗了内存,这正是我不应该在无缓冲结果中看到的(至少这是我的理解,为什么它被称为无缓冲)。 那么我很茫然。虽然准备好的语句默认情况下是无缓冲的,但get_result() 返回一个缓冲的结果集。所以我认为使用bind_result() 可以解决问题。 主要问题不是那一行的缓冲,而是所有已经读取的行的缓冲(不需要的行为)。下一个问题是我达到了 128MB 的脚本内存限制,尽管 memory_get_usage 只显示 80MB。都很奇怪。 【参考方案1】:

Mysql Documentation上有一个例子,所以你不要作为参数,只是运行一个方法。

<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) 
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();


$query  = "SELECT CURRENT_USER();";
$query .= "SELECT Name FROM City ORDER BY ID LIMIT 20, 5";

/* execute multi query */
if ($mysqli->multi_query($query)) 
    do 
        /* store first result set */
        if ($result = $mysqli->use_result())  //<----------- THIS LINE
            while ($row = $result->fetch_row()) 
                printf("%s\n", $row[0]);
            
            $result->close();
        
        /* print divider */
        if ($mysqli->more_results()) 
            printf("-----------------\n");
        
     while ($mysqli->next_result());


/* close connection */
$mysqli->close();
?>

https://dev.mysql.com/doc/apis-php/en/apis-php-mysqli.use-result.html

对于准备好的语句,您可以将属性设置为 false。

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

【讨论】:

我在 while 之前、get_result() 之前和查询之前在 3 个地方尝试了 $this-&gt;_connection-&gt;use_result();。内存消耗没有变化,在所有 3 个场景中的值相同。

以上是关于如何减少 PHP/MySQL 的内存消耗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Node.js Stream API 减少服务器端内存消耗?

如何使用 Node.js Stream API 减少服务器端内存消耗?

如何使用 Node.js Stream API 减少服务器端内存消耗?

Alexnet 神经网络:如何减少网络的消耗量?

如何减少 JVM 中的已提交堆内存

探索Java无反射机制,如何节省启动内存资源消耗!