как ускорить Mysql и PHP?

Я разрабатываю скрипт в своем localhst, используя PHP и mysql, и я имею дело с большими данными (около 2 миллионов записей для scintific research)

некоторые запросы мне нужно как-то в жизни (для анализа данных и подготовки данных); однако, это занимает очень много времени, например: теперь мой скрипт анализирует некоторые данные для более чем 4 часа

Я знал, что у меня могут возникнуть проблемы с оптимизацией моей базы данных я не эксперт

для пример я только что понял, что "индексирование" может быть полезно для ускорения запросов однако даже с индексированием некоторых столбцов мой скрипт все еще очень медленный

любая идея, как ускорить мой скрипт (в PHP и mysql)

Я использую XAMPP в качестве пакета сервера

Спасибо за помощь

С наилучшими пожеланиями

обновление 1:

часть моего медленного сценария, который занимает более 4 часов для обработки

$sql = "select * from urls";//10,000 record of cached HTML documents
$result = $DB->query($sql);
while($row = $DB->fetch_array($result)){
$url_id = $row["id"];
$content = $row["content"];

$dom = new DOMDocument();
@$dom->loadHTML($content);
$xpath = new DOMXPath($dom);
$row = $xpath->evaluate("/html/body//a");

for($i = 0; $i < $row->length; $i++) {
     // lots of the code here to deal with the HTML documents and some update and insert and select queries which query another table which has 1 million record
}

обновление 2:

У меня нет " JOIN "в моих quires или даже" IN"

это очень простые запросы

и не знаю! и я не знаю, как узнать, что вызывает медлительность?

это PHP или MYSQL?

6 ответов


прежде всего, чтобы иметь возможность эффективно оптимизировать, вам нужно знать, что это занимает время:

  • PHP делает слишком много вычислений ?
  • у вас слишком много SQL-запросов ?
  • у вас есть SQL-запросы, которые занимают слишком много времени ?
    • если да, то какие ?
  • где ваш сценарий проводит время ?

С этими сведениями вы можете попытаться выяснить :

  • если вы можете уменьшить количество SQL-запросов
    • например, если вы делаете один и тот же запрос снова и снова, вы, очевидно, тратите время
    • другая идея - "перегруппировать" запросы, если это возможно ; например, используйте только один запрос для получения 10 строк вместо 10 запросов, которые все получают одну строку.
  • если вы можете оптимизировать запросы, которые выполняются слишком долго
    • либо с помощью индексов -- те, которые полезны, как правило, зависят от соединений и условий, которые вы используете
    • или переписывание запросов, если они "плохие"
    • об оптимизации Select операторов, вы можете взглянуть на : 7.2. Оптимизация SELECT и других операторов
  • если PHP делает слишком много вычислений, можете ли вы сделать меньше вычислений ?
    • возможно, не пересчитывать подобные вещи снова и снова ?
    • или использование более эффективных запросов ?
  • если PHP требует времени, и SQL server не перегружен, использование параллелизма (запуск нескольких вычислений одновременно) также может помочь ускорить все это.

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


редактировать после редактирования

поскольку у вас есть только простые запросы, все может быть немного проще... Возможно.

  • прежде всего: вам нужно определить тип запросов, которые вы делаете.
    • Я предполагаю, что из всех ваших запросов вы можете определить некоторые "типы" запросов.
    • например : "select * from a where x = 12" и "select * from a where x = 14 " имеют один и тот же тип: тот же выбор, та же таблица, то же предложение where -- изменяется только значение
  • как только вы узнаете, какие запросы используются больше всего, вам нужно будет проверить, оптимизированы ли они: используя EXPLAIN поможет
    • (при необходимости, я уверен, что некоторые люди смогут помочь вам понять его вывод, если вы предоставите его вместе со схемой вас DB (таблицы + индексы))
    • при необходимости: создайте правильные индексы - это своего рода жесткая / конкретная часть ^^
    • это также для тех запросов, которые сокращение количества запросов может оказаться полезным...
  • когда вы закончите с часто используемыми запросами, пришло время пойти с запросами, которые занимают слишком много времени; используя microtime из PHP поможет вам узнать, какие из них


До этого, чтобы узнать, работает ли PHP слишком много, или если это MySQL, простой способ-использовать команду " top "в Linux или" process manager"(я не на windows, и не использовать его на английском языке-настоящее имя может быть что-то еще).

если PHP ест 100% CPU, у вас есть ваш виновник. Если MySQL ест весь процессор, у вас тоже есть виновник.

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


Я вижу из вашей части кода, что вы:

  • проходя через 10 000 элементов один за другим-это должно быть легко разделить их на 2 или более ломтиков
  • используя DOM и XPath, которые могут съесть некоторый процессор на стороне PHP

если у вас есть многоядерный процессор, идея (что я бы попытался, если я вижу, что PHP ест много процессора) будет распараллеливать.

например, вы можете иметь два экземпляра PHP-скрипта, работающих одновременно:

  • тот, который будет иметь дело с первой половиной URL-адресов
    • SQL-запрос для этого будет как "select * from urls where id < 5000"
  • и другой, который будет иметь дело со второй половиной URL-адресов
    • запрос будет типа "select * from urls where id >= 5000"

вы получите немного больше параллелизм в сети (возможно, не проблема) и в базе данных (база данных знает, как бороться с параллелизмом, и 2 скрипта, использующие ее, как правило, не слишком много), но вы сможете обрабатывать почти в два раза одинаковое количество документов за одно и то же время.

если у вас есть 4 процессора, разделив url-список на 4 (или даже больше ; выяснить методом проб и ошибок) запасные части тоже.


поскольку ваш запрос находится в одной таблице и не имеет группировки или упорядочения, маловероятно, что запрос будет медленным. Я ожидаю, что проблема заключается в размере и количестве полей контента. Похоже, что вы сохраняете весь HTML-код веб-страницы в своей базе данных, а затем вытаскиваете его каждый раз, когда хотите изменить пару значений на странице. Это ситуации следует избегать, если это вообще возможно.

большинство научных webapps (например, BLAST) имеют возможность экспортировать данные в виде текстового файла с разделителями, например csv. Если это так, вы можете подумать о реструктуризации таблицы url, чтобы иметь один столбец на поле данных в csv. Тогда ваши запросы на обновление будут значительно быстрее, так как вы сможете делать их полностью в SQL, а не вытягивать всю таблицу url в PHP, получая доступ и вытягивая одну или несколько других записей для каждой записи url, а затем обновляя таблицу.


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


знание запросов и структур таблиц было бы проще.

Если вы не можете дать им проверить, есть ли у вас оператор IN. MySQL имеет тенденцию слишком сильно замедляться. Также попробуйте запустить

EXPLAIN yourquery;

и посмотреть, как он выполняется. Иногда сортировка занимает слишком много времени. Старайтесь избегать сортировки на столбцы индекса.


Если вы не используете индексы, это может быть основной проблемой. Есть еще много оптимизационных подсказок и трюков. Лучше будет показать, т. е. ваш самый медленный запрос. Невозможно помочь без входных данных. Индексы и правильные соединения могут значительно ускорить это.

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

2 миллионов записей не так много.


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

в этом случае вы должны установить такой тест, а затем профилировать код. Вы можете использовать специальный профилировщик, например отладчик xdebug, или если вы считаете, что это слишком сложно настроить (не так сложно, но вы говорите, что вы уже немного в глубоком конце), вы можете чувствовать себя более комфортно с ручным подходом. Это означает запуск таймера перед частями кода и его остановку после, а затем печать результата. Затем вы можете сузить какая часть медленнее.

Как только вы получите это, мы можем дать более конкретные ответы, или, возможно, Вам будет ясно, что делать.


внутренние соединения быстрее, чем левые или правые соединения

всегда ускорял мои запросы, проходящие после и думающие конкретно о соединениях.

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