PHP занимает 90 раз больше времени для запуска запроса, чем клиент MySQL

Я выполняю MySQL-запрос с помощью скрипта PHP из командной строки (подготовленный запрос с использованием PDO для драйвера mysqlnd). Это простой запрос с одним левым соединением, возвращающим 100 строк и 7 маленьких столбцов на строку.

Когда я запускаю этот запрос в MySQL CLI (на том же компьютере, на котором запущен скрипт PHP), он занимает 0,10 секунды – даже при добавлении флага SQL_NO_CACHE.

Когда я запускаю этот запрос, подготовленный через PDO, он занимает более 9 секунд. Это только execute () – не включая время, которое требуется для вызова выборки.

Пример моего запроса:

SELECT HEX(al.uuid) hexUUID, al.created_on, IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id, pp.products_id product_id, al.action_id, al.last_updated FROM ActionAPI.actionLists al LEFT JOIN ActionAPI.publishers_products pp ON al.publisher_product_id = pp.id WHERE (al.test IS NULL OR al.test = 0) AND (al.created_on >= :since OR al.last_updated >= :since) ORDER BY created_on ASC LIMIT :skip, 100; 

Я не верю, что запрос виноват, учитывая, что каждый клиент MySQL, который я пробовал, запускал его почти мгновенно, но вот EXPLAIN для ударов:

 +----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+ | 1 | SIMPLE | al | index | created_on,last_updated | created_on | 8 | NULL | 100 | Using where | | 1 | SIMPLE | pp | eq_ref | PRIMARY | PRIMARY | 4 | ActionAPI.al.publisher_product_id | 1 | | +----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+ 2 rows in set (0.00 sec) 

Что в мире делает PDO, что занимает 8,9 секунды?

EDIT: Как указано в комментариях, я написал также версию mysql_query, и она имеет такую ​​же плохую производительность. Однако удаление части предложения WHERE заставляет его работать так же быстро, как клиент MySQL. Читайте дальше для ошеломляющих деталей.

У меня такая же проблема. Тот же запрос действовал по-разному при запуске из cli и PHP. Объясните в cli упоминание правильного использования индекса, в PHP ничего не было. Как я уже нашел, проблема была в том , что это был тип casting , в моем случае это было datetime. После того, как я специально использовал тип для сравнения, например. where datetime_column > cast('2014-01-12 12:30:01' as datetime) все работает.

Давая очень запоздалое обновление по этому вопросу:

Я не нашел причину, но оказалось, что EXPLAIN отличается от PHP в сравнении с CLI. Я не уверен, что какой-либо аспект подключения заставит MySQL выбрать использование другого поля для индекса, поскольку, насколько я знаю, эти вещи не должны быть связаны; но, увы, EXPLAIN от PHP показал, что соответствующий индекс не использовался, а CLI.

Решение в этом (непонятном) случае – это использование указателя . См. Строку «FROM» в этом модифицированном запросе из моего примера:

 SELECT HEX(al.uuid) hexUUID, al.created_on, IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id, pp.products_id product_id, al.action_id, al.last_updated FROM ActionAPI.actionLists al USE INDEX (created_on) LEFT JOIN ActionAPI.publishers_products pp ON al.publisher_product_id = pp.id WHERE (al.test IS NULL OR al.test = 0) AND (al.created_on >= :since OR al.last_updated >= :since) ORDER BY created_on ASC LIMIT :skip, 100; 

Надеюсь, это поможет кому-то!

PDO использует ресурсы для обработки результатов строк. Par, что с интерпретированным языком (PHP), и у вас будет сценарий, который требует больше времени для обработки, чем для MySQL, чтобы возвращать ваши результаты.

ПРИМЕЧАНИЕ. Использование mysql_select_db () или mysqli_select_db () выполняется намного быстрее, чем PDO.

Чтобы узнать больше о более быстрых PHP-запросах, см.: PHP: Какой самый быстрый способ запросить MySQL? Поскольку PDO болезненно медленный

Когда вы подключаетесь к командной строке, его ОЧЕНЬ, вероятно, будет использовать другой набор ярлыков, который при соединении с PHP.

Когда вы попросите его использовать индекс, он будет и потому, что наборы символов достаточно близки, чтобы не вызвать проблему (при догадках? Это зависит от вашей настройки таблицы и столбцов)

Попробуйте подтолкнуть некоторые указатели юникода, и это, вероятно, начнет возвращать плохие результаты.

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

UTF-8 vs Latin1 mysql, индексы, не используемые на utf-8

Дополнительная информация