我面临着一个根本不难解决的问题,但不知怎的我却做不到。这是场景:
我想将 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/