PHP-запрос выполняется медленно и обрезает значения в очень большой базе данных MySQL - PullRequest
0 голосов
/ 20 февраля 2012

Я имею дело с базой данных с около 30 таблицами и 10 миллионами уникальных записей.

Я пытаюсь использовать PHP для представления этих данных в определенном формате, используя echo "function" и помещая переменные с помощью {$ variable}.

Кроме того, данные являются иерархическими, поэтому я использовал команду соединения, чтобы включить несколько столбцов, и эта результирующая таблица, вероятно, имела размер около 15 столбцов.

Я запустил php-файл в Google Chrome, и он работал около 1 часа на довольно приличной машине с core2duo.

Но результирующий набор остановился на 18 тысячах записей - я, кстати, не ограничивал запрос.

Самая важная часть моего вопроса - как мне запустить этот файл, чтобы получить все результаты? Я не хочу сидеть там и устанавливать смещение снова и снова, если есть другой способ, я был бы очень признателен.

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

Спасибо

Обновление:

<?php
    include ('includes/functions.php');
    $connection=connectdb();

    $result=runquery('
    SELECT taxonomic_rank.rank as shortrank, scientific_name_element.name_element as shortname, sne.name_element as pname, tr.rank as prank
    FROM taxon_name_element
    LEFT JOIN scientific_name_element ON taxon_name_element.scientific_name_element_id = scientific_name_element.id
    LEFT JOIN taxon ON taxon_name_element.taxon_id = taxon.id
    LEFT JOIN taxonomic_rank ON taxonomic_rank.id = taxon.taxonomic_rank_id
    LEFT JOIN taxon_name_element AS tne ON taxon_name_element.parent_id = tne.taxon_id
    LEFT JOIN scientific_name_element AS sne ON sne.id = tne.scientific_name_element_id
    LEFT JOIN taxon AS tax ON tax.id = tne.taxon_id
    LEFT JOIN taxonomic_rank AS tr ON tr.id = tax.taxonomic_rank_id');
set_time_limit(0);
ini_set('max_execution_time',0);
    while($taxon_name_element = mysql_fetch_array($result)){
        if ($taxon_name_element['shortrank'] == 'species'){
            $subitem = $taxon_name_element['pname']."_".$taxon_name_element['shortname'];}

        else{$subitem = $taxon_name_element['shortrank']."_".$taxon_name_element['shortname'];}
        $parentitem = $taxon_name_element['prank']."_".$taxon_name_element['pname'];
        echo 
"\n<!-- http://invertnet.ill/med#{$subitem}\" -->\n
<owl:Class rdf:about=\"http://invertnet.ill/med#{$subitem}\">
    <rdfs:label xml:lang=\"en\">{$subitem}</rdfs:label>
    <rdfs:subClassOf rdf:resource=\"http://invertnet.ill/med#{$parentitem}\"/>
</owl:Class>\n\n";}
echo "<br>".count($taxon_name_element)." number of stuff";
?>

1 Ответ

1 голос
/ 20 февраля 2012

Считывание строк ниже, похоже, не является проблемой медленного запроса.

"Я запустил php-файл в Google Chrome, и он работал около 1 часа на довольно приличной машине core2duo.Но набор результатов остановился на уровне около 18 тысяч записей - я не ограничил запрос, например: "

Браузер - не лучший способ выбросить 10 миллионов записей, по крайней мере, Chrome :-),Мое предложение состоит в том, чтобы вы поместили некоторую нумерацию страниц в свой PHP-файл, чтобы вам не приходилось каждый раз устанавливать смещение вручную.Поместите простую ссылку «предыдущий-следующий», показывающую, скажем, 10000 записей на странице.

Если для запуска в браузере не требуется абсолютно другой способ, можно записать весь вывод в текстовый файл.

Некоторые примечания к запросу: есть ли конкретная причина для добавления LEFT JOIN дважды для каждой таблицы?Кажется, это как-то связано с taxon_name_element.parent_id, но так как я не уверен в требованиях и схеме таблиц, я не могу это комментировать.Но если запрос выполняется слишком медленно, рассмотрите возможность его оптимизации.

EDIT 1 - я попытался немного потренироваться в вашем запросе.И так как вам нужно как имя элемента, так и его родительское имя, я думаю, что можно сделать это в более простом запросе, не присоединяясь к одним и тем же таблицам дважды.Однако потребуется кодирование некоторой дополнительной логики.

Несколько наблюдений, которые я узнал из запроса:

  1. элемент и его родительское имя оба взяты из одной таблицы taxon_name_element
  2. есть еще один столбец «ранг», и он также идет из одной таблицы taxonomic_rank как для элемента, так и для его родителя
  3. Из этого конкретного соединения taxon_name_element.parent_id = tne.taxon_id я узнаю, что обаэлемент и его родитель находятся в одной таблице `taxon_name_element"

Теперь давайте посмотрим на более простой запрос:

SELECT `tr`.`rank` AS `shortrank`, `sne`.`name_element` AS `shortname`, `tne`.`parent_id`, `tne`.`taxon_id`
FROM `taxon_name_element` `tne`
LEFT JOIN `scientific_name_element` `sne` ON `tne`.`scientific_name_element_id` = `sne`.`id`
LEFT JOIN `taxon` `tax` ON `tne`.`taxon_id` = `tax`.`id`
LEFT JOIN `taxonomic_rank` `tr` ON `tr`.`id` = `tax`.`taxonomic_rank_id`;

Результирующий набор теперь будет содержать и taxon_id, и parent_id.Идея состоит в том, чтобы сохранить все результаты в массиве так, чтобы для KEY было установлено значение parent_id. Например:

$arrOutput = $arrParent = Array();
while ($row = mysql_fetch_array($result) {
    $arr = Array(
        'shortrank' => $row['shortrank'],
        'shortname' => $row['shortname'],
        'taxonid' => $row['taxon_id'],
        'parentid' => $row['parent_id']
        );
    $arrOutput[] = $arr;
    if (!empty($row['parent_id'])) {
        $arrParent[$row['parent_id']] = $arr;
    }
}
// $arrOutput is now the final array with all the results and you can loop through it like you do in your original code. When looping, the parent can directly be accessed using parent_id as the associative key.
foreach ($arrOutput as $arr) {
    $elementName = $arr['shortname'];
    $elementRank = $arr['shortrank'];
    $parentName = $arrParent[$arr['parentid']]['shortname'];
    $parentRank = $arrParent[$arr['parentid']]['shortrank'];
}

Надеюсь, что это имеет смысл! Что ж, приведенный выше курс нужен только в том случае, если исходный запрос стоит дорого.

ВНИМАНИЕ: приведенный выше код не проверен, и я только надеюсь, что он работает. Могут потребоваться незначительные изменения или исправления; -)

...