PHP 内存限制与 SQL 结果

标签 php sql

我面临着一个根本不难解决的问题,但不知怎的我却做不到。这是场景:

我想将 SQL 语句的结果提取到 PHP 数组中,看起来很简单吧?

问题是它给了我有关内存限制的错误( fatal error :内存不足(已分配 408944640)(尝试分配 805306376 字节))。

这是我的代码,它使用的语句给出的结果较少(我需要使用的语句包含 +/- 4000 条记录)。

$connect = @new mysqli($host, $db_user, $db_password, $db_name);

if($connect->connect_errno!=0)
{
    echo "Error: ".$connect->connect_errno."Why: ". $connect->connect_error;
}
else{
    $query = "SELECT meta_value, post_date 
FROM 
  wp_postmeta
  INNER JOIN 
  wp_posts
  ON wp_posts.ID=wp_postmeta.post_id 
where wp_posts.post_type ='shop_order' AND wp_postmeta.meta_key = '_order_total'";
    $sql_query=mysqli_query($connect,$query);
    if ($sql_query->num_rows > 0){
    while(($row = mysqli_fetch_assoc($sql_query))!== false){
        $result[] = $row;
    }} else {
        echo "0 results";
    }
}

echo json_encode($result);

不太清楚为什么它使用 0.8 GB 的内存(对于一个简单的语句来说似乎很重要。但是为了尝试一下,我已将 php.ini 文件中的 memory_limit 更改为:memory_limit=8192M。但它根本没有帮助(检查内存限制是否应用调用 php_info() 函数)。

谢谢大家!

最佳答案

不要将完整的结果表保存在内存中,否则您的服务器将很容易受到 DOS 攻击。服务器必须能够同时回复许多请求。一次仅处理一行并释放分配的内存。

您应该直接输出以逗号分隔的 JSON block 。

echo '[';

$sep = '';
while(($row = mysqli_fetch_assoc($sql_query))!== false){
    echo $sep . json_encode($row);
    $sep = ',';
}

echo ']';

或者,您可以将其缓存在临时文件中。

在较新的 MySql 版本上,您可以尝试:

SELECT JSON_OBJECT('meta_value', meta_value, 'post_date', post_date)
FROM wp_postmeta 
INNER JOIN wp_posts ON wp_posts.ID=wp_postmeta.post_id 
WHERE wp_posts.post_type ='shop_order' 
AND wp_postmeta.meta_key = '_order_total' 
INTO OUTFILE '/tmp/mysql-temp-GENERATED_UUID';

这会生成一个包含 JSON 行的文件,但不以逗号分隔。 如 mysqlserverteam.com 上所述聚合函数 JSON_ARRAYAGG 应该可以解决这个问题。 (不幸的是,我的安装有第三方存储库冲突,因此我无法测试它。)

SELECT JSON_ARRAGG(JSON_OBJECT('meta_value', meta_value, 'post_date', post_date))
FROM wp_postmeta 
INNER JOIN wp_posts ON wp_posts.ID=wp_postmeta.post_id 
WHERE wp_posts.post_type ='shop_order' 
AND wp_postmeta.meta_key = '_order_total' 
INTO OUTFILE '/tmp/mysql-temp-GENERATED_UUID';

如果 JSON_ARRAYAGG 由于某种原因导致问题,解决方法(至少在类 UNIX 系统上)是:

<?php
  $guid = bin2hex(openssl_random_pseudo_bytes(16));
  $tmp_filename = "/tmp/mysql-json-{$guid}.json";
  /* let MySql generate the tempfile, then */

  passthru('sed \'1 s/^/[/; $! s/$/,/ ; $ s/$/]/\' ' . $tmp_filename);
?>

关于PHP 内存限制与 SQL 结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58785498/

相关文章:

mysql - 计算两列sql之间的平均值

php - 如何连接两个数据库表并从连接表中返回最低价格

javascript - 接收数据json/jquery

mysql - 有没有简单的方法在mysql中生成测试数据?

sql - 对于每个 ID#,FInd 记录比同一列中给出的日期早/晚 1 年

mysql - 删除 SQL 中的 NULL 值 JOIN 和 SQL 中的 UNION 运算符

php - 如何在php中自动执行查询

php - 循环遍历 MySQL 结果

php - 用户 'domain\name'登录失败

php - 从 Symfony2 中的嵌入式 Controller 重定向