我知道在php中存在一些关于组装mysql数组的问题,但我的问题是,我希望将输出保存在JSON中。
情境: 我想从mysql获取数据,用它做一些事情(比如时间格式化)并用JSON输出。 JSON数据在浏览器中解析,并通过javascript图表显示。
问题: 所有这些都是有效的,但由于数据量巨大,我选择更大的日期范围输出时会出现内存不足错误。
由于需要JSON格式,直接发送每个x行数据的想法不起作用。几个JSON块不起作用,它需要是图表中的一个。
所以最后我需要对数据进行分块,但要将其保留为一个大的JSON。 (设置内存限制并不是真正的解决方案。)
思路: 一个想法是,让浏览器将日期范围分块并将数据作为块和&然后把它们放在一起。 当然这可行,但是如果有办法做这个服务器端,那就更好了。
代码:
private function getDB($date1, $date2){
$query = 'SELECT * FROM `db1`.`'.$table.'` WHERE `date` BETWEEN "'.$date1.'" AND "'.$date2.'" order by `date`;';
// date = datetime !
$result = $this->db->query($query);
$array = array();
while ( $row = $result->fetch_assoc () ) {
$array[] = array( strtotime($row[ 'date' ])*1000 , (float)$row[ 'var' ] );
// the formatting needs to be done, so the chart accepts it..
}
$result->close();
return json_encode($array);
}
答案 0 :(得分:0)
由于这不是一个选项,
ini_set("memory_limit","32M")
也许您可以将LIMIT添加到函数参数和查询:
private function getDB($date1, $date2, $start, $pageSize){
$query = 'SELECT * FROM `db1`.`'.$table.'` WHERE `date` BETWEEN "'.$date1.'" AND "'.$date2.'" order by `date` LIMIT $start, $pageSize;';
// date = datetime !
$result = $this->db->query($query);
$array = array();
while ( $row = $result->fetch_assoc () ) {
$array[] = array( strtotime($row[ 'date' ])*1000 , (float)$row[ 'var' ] );
// the formatting needs to be done, so the chart accepts it..
}
$result->close();
return json_encode($array);
}
然后在javascript中设置for循环,用Ajax调用它,每次递增$ start变量。
将每个responseText.substr(1).substr(-1)存储在一个数组中。
当responseText为“”时,所有记录都已返回。
。用逗号加入数组,然后添加一个新的开始和结束“{}”,你应该有一个等同于所有记录的JSON。
最小的解析,你将使用大部分的内置函数。
var startRec=0;
var pageSize=50;
var xmlhttp=new XMLHttpRequest();
var aryJSON=[];
var JSON;
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
if(xmlhttp.responseText==""){ //Might need to check for "{}" here instead of ""
//All records are received
JSON="{" + aryJSON.join(",") + "}";
aryJSON=[];
startRec=0
}else{
aryJSON.push(xmlhttp.responseText.substr(1).substr(-1));
startRec+=pageSize;
getNextPage();
}
}
}
function getNextPage(){
xmlhttp.open("GET","your.php?start=" + startRec + "&pageSize=" + pageSize,true);
xmlhttp.send();
}
答案 1 :(得分:0)
我建议您让服务器向浏览器发送创建表所需的内容。解析可能是一项繁重的任务,为什么客户要解除这个问题呢?
我会让你的后端向浏览器发送一种表示表格(即列表列表)的数据结构,所有的格式都已经完成。渲染表应该更快,占用内存更少。
答案 2 :(得分:0)
答案的一种方法是,在服务器上进行分块,通过发出JSON,删除前导[& ]
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
$array = array();
echo '[';
$started = false;
while ( $row = $result->fetch_assoc () ) {
$array[] = [ strtotime($row[ 'datetime' ])*1000 , (float)$row[ 'var' ] ];
if(sizeof($array) == 1000){
if($started){
echo ',';
}else{
$started = true;
}
echo substr(substr(json_encode($array),1), 0, -1);
// converting [[datetime1, value1],[datetime2, value2]]
// to [datetime1, value1],[datetime2, value2]
ob_flush();
$array = array();
}
}
if($started)echo ',';
$this->flushJSON($array);
echo ']';
flush();
$result->close();
这是有效的,并将ram使用率降低到40%。 似乎Apache正在缓冲某些东西,因此ram的使用随着时间的推移而增加,脚本正在运行。 (是的,同花顺工作,我调试了,这不是问题。)
但是由于剩余的增加,实现干净分块的最快方法是像alfadog67指出的那样。
另外,要提一下,我必须禁用输出压缩,否则apache不会直接刷新它。