PHP内存限制与SQL结果

时间:2019-01-03 12:58:33

标签: php sql

我面临的问题根本不应该解决,但我不知道如何解决。这是场景:

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

问题是它给了我关于memory_limit的错误(致命错误:内存不足(已分配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 。但这根本没有帮助(检查是否使用了memory_limit调用php_info()函数)。

谢谢你们!

2 个答案:

答案 0 :(得分:1)

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

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

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);
?>

答案 1 :(得分:0)

为什么不使用Wordpress这样查询和分页:

$args = array(
    "post_type" => "shop_order",
    "posts_per_page" => 1000,
    "post_status" => array("any"),
    "paged" => $paged, // pass your pagination here from javascript
    "meta_query" => array(
        "key" => "_order_total",
        "compare" => "EXISTS"
    )
);
$custom_posts = get_posts($args);

echo json_encode($custom_posts);