我有一个报告页面,用于处理数据库表中约700,000条记录。我可以使用分页在网页上显示此内容以分解结果。但是,我导出到PDF / CSV函数依赖于立即处理整个数据集,而我的内存限制大约为250k行。
我觉得增加内存限制并不舒服,而且我没有能力使用MySQL的保存到outfile中来提供预先生成的CSV。但是,我无法真正看到使用Drupal提供大型数据集的方法:
$form = array();
$table_headers = array();
$table_rows = array();
$data = db_query("a query to get the whole dataset");
while ($row = db_fetch_object($data)) {
$table_rows[] = $row->some attribute;
}
$form['report'] = array('#value' => theme('table', $table_headers, $table_rows);
return $form;
有没有办法解决基本附加到巨大数组阵列的问题?目前我还没有看到如何通过Drupal提供任何有意义的报告页面。
由于
答案 0 :(得分:4)
有了这么大的数据集,我会使用Drupal的Batch API,它允许将时间密集型操作分成批次。它对用户来说也更好,因为它会给他们一个进度条,指示操作需要多长时间。
通过打开临时文件启动批处理操作,然后在每个新批处理中向其添加新记录,直到完成为止。最后一页可以进行最终处理,以将数据作为cvs或转换为PDF。你可能也想在后面添加一些清理。
答案 1 :(得分:1)
如果要生成PDF或CSV,则不应使用Drupal本机功能。如何写入while循环中的输出文件?这样,在给定时间内只有一个结果集在内存中。
答案 2 :(得分:0)
目前,您将所有内容存储在数组$table_rows
。
当你从数据库中读取报告时,你是否不能刷新报告的至少部分(例如,每隔那么多行)以释放一些内存?我不明白为什么它应该只能一次写入csv。
答案 3 :(得分:0)
我觉得增加内存限制感觉不舒服
增加内存限制并不意味着每个php进程都会使用该内存量。但是你可以用自定义内存限制执行php的cli版本 - 但这也不是正确的解决方案......
我没有能力使用MySQL的保存到outfile中来提供预先生成的CSV
然后不要将它全部保存在数组中 - 当从数据库中获取它时,将每一行写入输出缓冲区(IIRC,整个结果集缓存在有限的php内存之外)。或者直接将其写入文件,然后在文件完成并关闭时进行重定向。
下进行。
答案 4 :(得分:0)
您应该使用pager_query包含分页,并将结果分成每页50-100。这应该会有很大帮助。你说你想使用分页,但我没有在代码中看到它。
答案 5 :(得分:0)
要记住的另一件事是,在PHP5(5.3之前)中,将数组分配给新变量或将其传递给函数复制数组并且不创建引用。您可能正在创建相同数据的许多副本,如果没有未设置或超出范围,则无法对其进行垃圾回收以释放内存。在可能的情况下,使用引用对原始数组执行操作可以节省内存
function doSomething($arg){
foreach($arg AS $var)
// a new copy is created here internally: 3 copies of data exist
$internal[] = doSomethingToValue($var);
return $internal;
// $arg goes out of scope and can be garbage collected: 2 copies exist
}
$var = array();
// a copy is passed to function: 2 copies of data exist
$var2 = doSomething($var);
// $var2 will be a reference to the same object in memory as $internal,
// so only 2 copies still exist
如果将$ var设置为函数的返回值,则可以对旧值进行垃圾收集,但直到赋值后才能进行垃圾收集,因此短时间内仍需要更多内存
function doSomething(&$arg){
foreach($arg AS &$var)
// operations are performed on original array data:
// only two copies of an array element exist at once, not the whole array
$var = doSomethingToValue($var);
unset($var); // not needed here, but good practice in large functions
}
$var = array();
// a reference is passed to function: 1 copy of data exists
doSomething($var);
答案 6 :(得分:0)
我处理如此庞大的报告的方法是使用php cli / Java / CPP / C#生成它们(即CRONTAB)+使用mysql所拥有的无缓冲查询选项。 在磁盘上完成文件/报告创建后,您可以给它一个链接......