Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: PDO: prepare или прямые запросы в простых SELECT-ах?
Форумы портала PHP.SU » » Вопросы новичков » PDO: prepare или прямые запросы в простых SELECT-ах?

Страниц (2): [1] 2 »
 

1. Anchor - 27 Мая, 2014 - 19:20:26 - перейти к сообщению
Подскажите плиз, что в подобных запросах рациональнее использовать(что будет быстрее работать)? Делать такие запросы в PDO с prepare, либо делать их напрямую ->query() ?

1
PHP:
скопировать код в буфер обмена
  1. $query = "SELECT $fields_str FROM $db_table";
  2. $STH = $PDO->prepare($query);
  3. $STH->execute();
  4. $table_data = $STH->fetchAll(PDO::FETCH_ASSOC);

2
PHP:
скопировать код в буфер обмена
  1. $query = "SELECT $fields_str FROM $db_table WHERE id=:id";
  2. $STH = $PDO->prepare($query);
  3. $STH->bindParam(':id', $item_id);
  4. $STH->execute();
  5. $item = $STH->fetch(PDO::FETCH_ASSOC);


Или?
1
PHP:
скопировать код в буфер обмена
  1. $query = "SELECT $fields_str FROM $db_table";
  2. $result = $PDO->query($query);

2
PHP:
скопировать код в буфер обмена
  1. if (!is_numeric($item_id)) error(404, '');
  2. $query = "SELECT $fields_str FROM $db_table WHERE id=$item_id";
  3. $result = $PDO->query($query);
2. OrmaJever - 27 Мая, 2014 - 19:33:40 - перейти к сообщению
чисто теоретически обычные запросы будут быстрее, но в подготовленных запросах код лучше выглядит, и иногда в цикле можно красиво добавлять или обновлять
3. Anchor - 27 Мая, 2014 - 19:48:49 - перейти к сообщению
OrmaJever пишет:
но в подготовленных запросах код лучше выглядит

Можно уточнить, в каком плане лучше выглядит, что под этим имелось ввиду? Не понял просто

Плэйсхолдеры, я правильно понимаю, здесь вообще нет смысла использовать? :

PHP:
скопировать код в буфер обмена
  1. if (!is_numeric($item_id)) error(404, '');
  2. $query = "SELECT $fields_str FROM $db_table WHERE id=$item_id";
  3.  
  4. //$bottom_lim, $top_lim зависят, и расчитываются от параметра $_GET['page']
  5. $query = "SELECT $fields_str FROM $db_table LIMIT $bottom_lim, $top_lim";
4. OrmaJever - 27 Мая, 2014 - 19:55:25 - перейти к сообщению
Anchor пишет:
Можно уточнить, в каком плане лучше выглядит, что под этим имелось ввиду? Не понял просто

напишу пример на mysqli так как лучше его знаю, но суть одна и таже.
PHP:
скопировать код в буфер обмена
  1. // 1
  2. $mysqli->query('UPDATE table SET row1 = "'.$mysqli->escape_string($value1).'", row2 = "'.$mysqli->escape_string($value2).'" WHERE id = '. (int)$id);
  3. // 2
  4. $p = $mysqli->prepare('UPDATE table SET row1 = ?, row2 = ? WHERE id = ?');
  5. $p->bind_param('ssi', $value1, $value2, $id);
  6. $p->execute();

какой вариант понятнее?
(Добавление)
и про циклы

PHP:
скопировать код в буфер обмена
  1. // 1
  2. foreach($array as $value) {
  3.     $mysqli->query('INSERT INTO table SET row1 = "'.$mysqli->escape_string($value).'", row2 = "'.$mysqli->escape_string($value).'" WHERE id = '. (int)$id);
  4. }
  5. // 2
  6. $p = $mysqli->prepare('INSERT INTO table SET row1 = ?, row2 = ? WHERE id = ?');
  7. foreach($array as $value) {
  8.     $p->bind_param('ssi', $value, $value, $id);
  9.     $p->execute();
  10. }

вот здесь возможно второй вариант будет работать быстрее, нужно протестить ради интереса
5. Anchor - 28 Мая, 2014 - 04:15:14 - перейти к сообщению
Ок, thanks. А выигрыш в скорости происходит только в рамках одного http-запроса? Т.е.: перешли по УРЛ(сделали http-запрос), далее при выполнении php, произошла подготовка SQL запроса (prepare); теперь (в рамках этого же http-запроса) делаем неск-ко execute() например в цикле. Вопрос: выигрываем по скорости только в рамках этого запроса? А если мы стали ходить, по страницам товаров, например (другие http-запросы), где меняется только $item_id в "WHERE id=$item_id" - мы не получаем выигрыша по скорости в этом случае? (там же вроде как кешируется шаблон SQL запроса на стороне СУБД)
6. Мелкий - 28 Мая, 2014 - 09:54:00 - перейти к сообщению
Anchor пишет:
(там же вроде как кешируется шаблон SQL запроса на стороне СУБД)

У mysql prepare кэшируется только в рамках одного соединения.
У нормальный СУБД - будет выигрыш. Правда, есть другие тараканы с кэшированием плана запроса. Но этим пусть сама СУБД и занимается.

Используйте всегда prepare для подстановки значений.
Напрямую query можно пнуть, если запрос константный и задаётся только в коде.
7. ПТО - 28 Мая, 2014 - 10:01:38 - перейти к сообщению
Если не ошибаюсь, с prepare будет быстрее только при > 1000 запросах
(Добавление)
Как у OrmaJever:
foreach($array as $value) {

}
8. Stierus - 28 Мая, 2014 - 10:18:01 - перейти к сообщению
prepare используют не что бы повысить скорость, а что бы обезопасить свое приложение.
9. EuGen - 28 Мая, 2014 - 10:56:09 - перейти к сообщению
SQL Injections
10. esterio - 28 Мая, 2014 - 11:15:33 - перейти к сообщению
как правило prepare быстрее при запросах в цикле. но на праутике таких запросов мало. поетому скорее безопасность чем скорость
11. teddy - 28 Мая, 2014 - 12:01:09 - перейти к сообщению
Я думаю скорость работы приложения в целом увеличивается

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

PHP:
скопировать код в буфер обмена
  1. $message = $dbh->quote('Двадцать тысяч символов');
  2. $dbh->query("INSERT INTO `messages` (`message`) VALUES('$message')");


И теперь тоже самое но с использованием подготовленных запросов

PHP:
скопировать код в буфер обмена
  1. $stmt = $dbh->prepare('INSERT INTO `messages` (`message`) VALUES(:message)');
  2. $stmt->execute(array(':message' => $message));


Т.е экранирования во втором случае не было, и метод quote не тратил время на парсинг строки размеров в 20к символов.
12. esterio - 28 Мая, 2014 - 12:08:36 - перейти к сообщению
teddy
очень спороно. нужно делать тесты. но и ети тесты будут синтетическими. лично я делал тесты при простых запросах со вставкой рандомной строкы. екранирование дало вииграш на несколько тисячних секунд. как по мне економия на спичках. и да еще один нюанс. те же фреймворки кроме безопасности и скорости используют prepare ибо проще реализация типа такой (Пример с Yii)
PHP:
скопировать код в буфер обмена
  1. Yii::app()->db->createCommand('SELECT * FROM table WHERE id=:id LIMIT 1')->queryRow(true, array(':id' => $id));

тоесть запросы которые формируют всякие DAO, ActiveRecord и прочие абстракции и параметры для них. Как по мне такое проще реализировать на prepare нежели preg_replace
13. teddy - 28 Мая, 2014 - 12:24:44 - перейти к сообщению
esterio
Насчет тестов согласен, я не тестил, но если подумать логически то лучше не напрягать quote особенно тогда когда и без этого можно обойтись(да и если фигачить в цикле много запросов то выигрыш будет явный я думаю)+ подготовленные запросы дают нам возможность не беспокоиться об экранировании. Поэтому лично мой выбор - везде использовать именно подготовленные запросы.
14. Anchor - 28 Мая, 2014 - 12:26:06 - перейти к сообщению
Каков принцип работы плейсхолдеров? Я понимаю, если происходит подстановка строковых параметров. Тогда, да, как понимаю, там этот параметр, вылижут, отэкранируют, проверят, и пр. Со строковыми параметрами - безусловно удобнее.

Но: не могу понять, в данном, конкретном случае:

CODE (SQL):
скопировать код в буфер обмена
  1. 'SELECT * FROM table WHERE id=:id LIMIT 1'

Могу же я сделать, просто так:

PHP:
скопировать код в буфер обмена
  1. if (!is_numeric($item_id)) error(404, '');

Ведь 100% знаю, что $item_id теперь пролезет только ЧИСЛОВОЙ. Или все же есть нюансы и здесь?
15. caballero - 28 Мая, 2014 - 12:26:45 - перейти к сообщению
Цитата:
prepare используют не что бы повысить скорость, а что бы обезопасить свое приложение.
.
prepare не имеет никого отношения к биндингу параметров. Это разные ничем не связанные вещи.


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

 

Powered by ExBB FM 1.0 RC1