我需要以JSON格式输出至少500,000条记录,最初使用的是以下内容
<?php
$con=mysqli_connect("localhost",$username,$password,databaseName);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$query = "the query here";
$result = mysqli_query($con,$query);
$rows = array();
while($r = mysqli_fetch_array($result)) {
$rows[] = $r;
}
echo json_encode($rows);
mysqli_close($con);
?>
也就是说,我将所有内容存储在变量中,然后在最后输出。
但是我发现在记录很大的情况下,我遇到了内存不足错误Allowed memory size of xxxxx bytes exhausted (tried to allocate xx bytes)
然后,我修改了上述内容以解决以下问题:
<?php
//Same as above
$result = mysqli_query($con,$query);
$numItems = mysql_num_rows($result);
$i = 0;
echo "[";
while($r = mysqli_fetch_array($result)) {
echo json_encode($r);
if(++$i !== $numItems) {
echo ",";
}
}
echo "]";
mysqli_close($con);
?>
我没有在最后输出行,而是在每次MySQL迭代期间输出每一行。因此,无需将所有行都存储在变量缓冲区中。
对于我拥有的50万行记录,它运行得很好。但是,当我在线搜索时,没有人做我做的事情。所以我的问题是:
echo json_encode()
方法可以安全使用吗?答案 0 :(得分:2)
由于您没有足够的内存将整个JSON文档保存在内存中,因此请考虑使用一种更有效的内存替代方法:
将每一行作为一个简单的数组转储出来,这样可以避免重复每一行的键。例如,代替:
[
{ "id": 1, "valueA": "A", ... },
{ "id": 2, "valueA": "A", ... },
...
]
考虑这样做:
{
"columns": [ "id", "valueA", ... ],
"values": [
[ 1, "A" ],
[ 2, "A" ],
...
]
}
实际上会导致大大个较小的文档。
您可能还想考虑使用JSON Streaming或行分隔的JSON,在其中每行输出一个文档:
{ "id": 1, "valueA": "A", ... }
{ "id": 2, "valueA": "A", ... }
虽然不会减少结果的整体大小,但确实可以简化另一端的解析。阅读器仅需要足够的内存来容纳最大的单行文档,而不是一次存储所有500K。
如果您的Web服务器支持流式传输结果,这也可能会带来性能上的好处,因为您可以在所有记录都加载之前开始传输记录。
考虑:如果您没有足够的内存来完整地生成文档,那么如果没有手边的 ton 内存,有人怎么能使用它呢?行分隔的JSON更加易于阅读,您可以将其流式传输,快速对其进行迭代。