如何使用AJAX分解大型MySQL查询和缓存数据?

时间:2012-06-26 01:51:02

标签: php mysql ajax timeout

我正在使用TCPDF动态创建PDF文档。生成这些PDF的一些查询包含超过1,000条记录,我的服务器超时查询(内部服务器错误)。我正在使用PHP和MySQL。

如何使用AJAX将大型MySQL查询解析为较小的块,缓存数据并重新组合结果,以防止服务器超时?

这是我目前的代码:

require_once('../../libraries/tcpdf/tcpdf.php');

$pdf = new TCPDF();

$prows = fetch_data($id);

$filename = '../../pdf_template.php';

foreach ($prows AS $row) {

    $pdf->AddPage('P', 'Letter'); 
    ob_start(); 

    require($filename);

    $html .= ob_get_contents();
    ob_end_clean();

    $pdf->writeHTML($html, true, false, true, false, '')

}

$pdf->Output('documents.pdf', 'D');

2 个答案:

答案 0 :(得分:0)

如果绝对必须在每隔时间生成数据,那么您可以将查询分块为100行,将数据缓存在文件系统上(或者更好,在APC / WinCache / XCache / MemCache中)然后在最后的AJAX调用(Finalquery = true),加载缓存,生成PDF和清除缓存。

我假设您无法更改脚本的最长运行时间,例如<?php set_time_limit(0);

流程将如下:

  • 为查询操作生成唯一ID
  • 在客户端,通过初始调用php脚本获取最大行数(选择计数...等)。
  • 然后,将它除以10,100,1000,但是要将其分成多个请求。
  • 为每个具有唯一ID的块(行0,100,100,200)运行AJAX请求。
  • 在服务器端,您选择该行数/行,并将其放入某个商店。我熟悉WinCache(我在Windows上开发PHP ...),所以将它添加到usercache:wincache_ucache_add( $uniqueId . '.chunk' . $chunkNumber, $rows);
  • 与此同时,在客户端,跟踪所有AJAX请求。完成每个操作后,调用生成PDF函数服务器端。给出块数和唯一ID。
  • 在服务器端,从缓存中获取所有内容。 $rows = array_merge( wincache_ucache_get($uniqueId . '.chunk'. $chunkNumber1), wincache_ucache_get($uniqueId . '.chunk'. $chunkNumber2) );
  • 清除缓存:wincache_ucache_clear();
  • 生成PDF并将其返回。

请注意,您应该只是手动或通过抽象层或ORM中的功能来缓存查询结果。

答案 1 :(得分:0)

尝试像PEAR cache_lite这样的简单缓存。在缓慢或关闭期间,您可以创建一个实用程序来运行和缓存所需的所有记录。然后,当用户请求PDF时,您可以访问缓存数据,而无需访问数据库。此外,您可以只使用表上的timestamp字段并请求自缓存数据以来已更改的数据库记录,这将显着降低您必须实时从数据库中检索的当前记录数。

<?php
include 'Cache/Lite/Output.php';
$options = array(
    'cacheDir' => '/tmp/cache/',
    'lifeTime' => 3600,
    'pearErrorMode' => CACHE_LITE_ERROR_DIE,
    'automaticSerialization' => true
);

$cache = new Cache_Lite_Output($options);
if( $data_array = $cache->get('some_data_id') ) {
    $prows = $data_array;
} else {
    $prows = fetch_data($id);
    $cache->save($prows);
}

print_r($prows);

?>