使用json编码分块MySQL数组

时间:2014-08-15 13:00:07

标签: javascript php mysql json chunking

我知道在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);
}

3 个答案:

答案 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不会直接刷新它。