Буферизация вывода и большие наборы результатов MySQL в PHP 5 - PullRequest
2 голосов
/ 15 сентября 2009

Я пытаюсь создать XML-фид из базы данных с огромной таблицей, почти 4 тыс. Записей. Я хочу использовать буферизацию вывода, чтобы заставить его выплевывать XML, но сценарий все еще продолжает истекать.

ob_start();
$what = 'j.*, (select description from tb_job_type as jt WHERE jt.jobtype_id =  j.job_type_id) as job_type,';
$what .= '(select description from tb_location as l WHERE l.location_id = j.location_id) as location,';
$what .= '(select description from tb_industry as i WHERE i.industry_id = j.industry_id) as industry';
$where = ('' != $SelectedType) ?  'j.job_ad_type="' . $SelectedType .'"' : '';
$process = $db->executeQuery('SELECT ' . $what . ' FROM tb_job_ad as j' . $where);

while($result = mysql_fetch_array($process))
{
    $result['job_title_url']        = $form->urlString($result['job_title']);
    $result['job_title']            = htmlspecialchars($result['job_title'], ENT_QUOTES, 'UTF-8');
    $result['short_description']    = htmlspecialchars($result['short_description'], ENT_QUOTES, 'UTF-8');
    $result['full_description']     = htmlspecialchars($result['full_description'], ENT_QUOTES, 'UTF-8');
    $result['company_name']         = ucwords(strtolower($result['company_name']));
    $tpl->assignToBlock('ITEMS', $result);
}
$cheese = ob_get_contents();    
$actualize = $tpl->actualize('FEED');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-type: text/xml");
echo $actualize;
ob_flush();
print $cheese;
ob_end_clean();

Кажется, это строка, которая заставляет скрипт задыхаться:

$tpl->assignToBlock('ITEMS', $result);

Помогите пожалуйста?

Спасибо

Midiane.

Ответы [ 3 ]

1 голос
/ 15 сентября 2009

Может быть, у вас довольно медленный запрос?
Сравните вывод

set_time_limit(60);
$process = $db->executeQuery('EXPLAIN SELECT ' . $what . ' FROM tb_job_ad as j' . $where);
while($result = mysql_fetch_array($process, MYSQL_ASSOC)) {
  echo join(' | ', $result), "<br />\n";
}

с Оптимизация запросов с помощью EXPLAIN .

0 голосов
/ 15 сентября 2009

Время ожидания почти наверняка происходит из-за того, что ваш запрос медленный - и вы почти наверняка можете улучшить его производительность, убедившись, что у вас есть правильные проиндексированные столбцы, и выполнив некоторые JOIN-ы.

Что если вы переписали конструкцию запроса следующим образом:

$q = 'SELECT 
  j.*, 
  jt.description as job_type, 
  l.description as location, 
  i.description as industry
FROM tb_jobs AS j
INNER JOIN tb_job_type AS jt ON j.job_type_id = jt.jobtype_id 
INNER JOIN tb_location AS l ON j.location_id = l.location_id
INNER JOIN tb_industry AS i ON j.indsutry_id = i.industry_id';

if (! empty($SelectedType)){
  $where = "WHERE j.job_ad_type = '$SelectedType'";
}else{
  $where = '';
}

$q .= $where;

Убедитесь, что все столбцы внешних ключей (j.location_id и т. Д.) Проиндексированы.

Если вы хотите, чтобы вывод начинался раньше, вам нужно - запросить базу данных - Вывести все ваши заголовки и т. Д. - напишите вам пока цикл как:

ob_end_flush();flush();
while($row = mysql_fetch_assoc($process)
{
  ob_start();
  //build your ITEM and echo it here
  ob_end_flush(); flush();
}

PS: Я также заметил еще один вопрос, связанный с SQL, здесь, на SO. Я думаю, что вы очень хорошо обслужитесь, если будете лучше понимать, как работает SQL. Я настоятельно рекомендую получить копию " SLQ Clearly Explained " - она ​​дает именно то, что обещает заголовок - четкое объяснение SQL (в общем, не увязая в обсуждении различных реализаций)

0 голосов
/ 15 сентября 2009

Вы можете использовать set_time_limit (0), чтобы позволить вашему сценарию работать вечно без какого-либо таймаута и ждать, пока он не завершит выполнение.

...