Mysql PDO Эффективность подготовленного заявления - PullRequest
4 голосов
/ 29 марта 2011

Я беру на себя PHP-приложение, которое использует подготовленные операторы MySQL PDO для каждого запуска SQL-оператора.Я знаю, что подготовка SQL может быть более эффективной, когда вы собираетесь выполнить много итераций одного и того же оператора.

$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute(array(150, 'red'));
$red = $sth->fetchAll();
$sth->execute(array(175, 'yellow'));
$yellow = $sth->fetchAll();

Однако приложение, которое я беру на себя, имеет встроенный слой поверх PDO, которыйвызывает общую функцию execute, и кажется, что она подготавливает каждый отдельный запрос SQL.Например:

$query = self::$DB->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$query->execute($bindvars);

Если приложение выполняет несколько сотен или тысяч операторов SQL INSERT INTO ...... ON DUPLICATE KEY UPDATE, создает ли шаг $ DB-> prepare () созданиезначительные накладные расходы, если он запускается каждый раз?

Большое спасибо, Джейсон.

Ответы [ 3 ]

3 голосов
/ 29 марта 2011

Из документации:

Вызов PDO :: prepare () и PDOStatement :: execute () для операторов, которые будут выполняться несколько раз с разными значениями параметров, оптимизирует производительность вашего приложения, позволяядрайвер для согласования кэширования на стороне клиента и / или сервера плана запроса и метаинформации ...

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

2 голосов
/ 29 марта 2011

Помимо повторного использования запроса, основной причиной *1002* использования подготовленных операторов в PDO является использование привязки заполнителя.

$query = self::$DB->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$query->execute($bindvars);

В этом коде заполнители вопросительных знаков (или :named), присутствующие в переменной $sql, заменены на значения в массиве $bindvars. Эта замена гарантирует, что переменные правильно заключены в кавычки и экранированы, что значительно усложняет выполнение SQL-инъекции .

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

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

(С другой стороны, я не могу поручиться за производительность курсора MySQL ...)

1 голос
/ 29 марта 2011

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

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

...