Простые хранимые процедуры медленнее, чем стандартные запросы!Зачем? - PullRequest
0 голосов
/ 29 октября 2011

Одним из преимуществ хранимых процедур является хорошая скорость. Я провел несколько тестов и получил странные результаты!

Сценарий: есть 2 таблицы InnoDB, Агенты и Компании. Каждый агент связан с ОДНОЙ компанией через FK и проиндексирован правильно. Пожалуйста, посмотрите на способы ниже:

Два простых запроса:

$agent = $pdo->query("SELECT * FROM agents WHERE id=3")->fetch(PDO::FETCH_ASSOC);
$company = $pdo->query("SELECT name FROM companies WHERE id='$agent[company]'")->fetch(PDO::FETCH_ASSOC);
$name = $company['name'];
// 0.000793933868408
// 0.000741958618164

Один запрос с JOIN

$agent = $pdo->query("
    SELECT agents.*, companies.name FROM agents
    LEFT JOIN companies ON companies.id=agents.company
    WHERE agents.id=3
")->fetch(PDO::FETCH_ASSOC);
$name = $agent['name'];
// 0.000327110290527
// 0.00028395652771

Два вызова SP:

$agent = $pdo->query("CALL agents('3')")->fetch(PDO::FETCH_ASSOC);
$partner = $pdo->query("CALL companies('$agent[company]')")->fetch(PDO::FETCH_ASSOC);
$name = $agent['name'];
// 0.010176897049
// 0.010200023651

/*
CREATE PROCEDURE `agents`(agent INT(10))
BEGIN SELECT * FROM agents WHERE id=agent; END

CREATE PROCEDURE `companies`(company INT(10))
BEGIN SELECT * FROM companies WHERE id=company; END
*/

Один вызов SP с JOIN:

$agent = $pdo->query("CALL agents('3')")->fetch();
$name = $agent['name'];
// 0.00241208076477
// 0.00252604484558

/*
CREATE PROCEDURE `agents`(agent INT(10))
BEGIN
    SELECT agents.*, companies.name FROM agents
    LEFT JOIN companies ON companies.id=agents.company
    WHERE agents.id=agent;
END
*/

Как эти простые SP медленны, как вы видели? Может ли это вызвать PDO или системная среда? Как я знаю, SP отлично подходит для простых запросов, но здесь .....

Обратите внимание, что указанное выше время было записано после трехкратного запуска.

Спасибо AHHP

1 Ответ

3 голосов
/ 29 октября 2011

Первое: запросы кешируются. Запуск их более одного раза, в основном, покажет вам, как быстро MySQL может получить свой предыдущий результат из кэша. Вы можете предотвратить это (немного), добавив SQL_NO_CACHE после ключевого слова SElECT.

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

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

Тогда запросы, которые вы выполняете в хранимой процедуре, не совпадают с отдельным запросом. В отдельном запросе вы вводите точное значение в строке запроса перед его отправкой в ​​MySQL, в то время как в хранимой процедуре у вас фактически есть параметризованный запрос, в котором вы добавляете значение в качестве параметра в механизм mysql (хотя этот факт немного скрытый синтаксисом вызова запросов в хранимом процессе. Это означает, что вызов этой процедуры в первый раз заставляет MySQL снова анализировать этот запрос, в то время как версия с «постоянным значением» уже кэширована.

Итак, в заключение, ваш тест неверен.

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

...