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

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: PDO: prepare или прямые запросы в простых SELECT-ах?

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


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

> Без описания
Anchor
Отправлено: 27 Мая, 2014 - 19:20:26
Post Id


Новичок


Покинул форум
Сообщений всего: 57
Дата рег-ции: Май 2014  


Помог: 0 раз(а)




Подскажите плиз, что в подобных запросах рациональнее использовать(что будет быстрее работать)? Делать такие запросы в 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);

(Отредактировано автором: 27 Мая, 2014 - 19:21:40)

 
 Top
OrmaJever Модератор
Отправлено: 27 Мая, 2014 - 19:33:40
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




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


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Anchor
Отправлено: 27 Мая, 2014 - 19:48:49
Post Id


Новичок


Покинул форум
Сообщений всего: 57
Дата рег-ции: Май 2014  


Помог: 0 раз(а)




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";

(Отредактировано автором: 27 Мая, 2014 - 19:51:12)

 
 Top
OrmaJever Модератор
Отправлено: 27 Мая, 2014 - 19:55:25
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




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. }

вот здесь возможно второй вариант будет работать быстрее, нужно протестить ради интереса


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Anchor
Отправлено: 28 Мая, 2014 - 04:15:14
Post Id


Новичок


Покинул форум
Сообщений всего: 57
Дата рег-ции: Май 2014  


Помог: 0 раз(а)




Ок, thanks. А выигрыш в скорости происходит только в рамках одного http-запроса? Т.е.: перешли по УРЛ(сделали http-запрос), далее при выполнении php, произошла подготовка SQL запроса (prepare); теперь (в рамках этого же http-запроса) делаем неск-ко execute() например в цикле. Вопрос: выигрываем по скорости только в рамках этого запроса? А если мы стали ходить, по страницам товаров, например (другие http-запросы), где меняется только $item_id в "WHERE id=$item_id" - мы не получаем выигрыша по скорости в этом случае? (там же вроде как кешируется шаблон SQL запроса на стороне СУБД)

(Отредактировано автором: 28 Мая, 2014 - 04:15:51)

 
 Top
Мелкий Супермодератор
Отправлено: 28 Мая, 2014 - 09:54:00
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Anchor пишет:
(там же вроде как кешируется шаблон SQL запроса на стороне СУБД)

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

Используйте всегда prepare для подстановки значений.
Напрямую query можно пнуть, если запрос константный и задаётся только в коде.


-----
PostgreSQL DBA
 
 Top
ПТО
Отправлено: 28 Мая, 2014 - 10:01:38
Post Id



Посетитель


Покинул форум
Сообщений всего: 395
Дата рег-ции: Янв. 2012  


Помог: 3 раз(а)




Если не ошибаюсь, с prepare будет быстрее только при > 1000 запросах
(Добавление)
Как у OrmaJever:
foreach($array as $value) {

}
 
 Top
Stierus Супермодератор
Отправлено: 28 Мая, 2014 - 10:18:01
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




prepare используют не что бы повысить скорость, а что бы обезопасить свое приложение.
 
My status
 Top
EuGen Администратор
Отправлено: 28 Мая, 2014 - 10:56:09
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)






-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
esterio
Отправлено: 28 Мая, 2014 - 11:15:33
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




как правило prepare быстрее при запросах в цикле. но на праутике таких запросов мало. поетому скорее безопасность чем скорость
 
 Top
teddy
Отправлено: 28 Мая, 2014 - 12:01:09
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




Я думаю скорость работы приложения в целом увеличивается

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

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к символов.
 
 Top
esterio
Отправлено: 28 Мая, 2014 - 12:08:36
Post Id



Активный участник


Покинул форум
Сообщений всего: 5025
Дата рег-ции: Нояб. 2012  
Откуда: Украина, Львов


Помог: 127 раз(а)




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
 
 Top
teddy
Отправлено: 28 Мая, 2014 - 12:24:44
Post Id


Участник


Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013  


Помог: 91 раз(а)




esterio
Насчет тестов согласен, я не тестил, но если подумать логически то лучше не напрягать quote особенно тогда когда и без этого можно обойтись(да и если фигачить в цикле много запросов то выигрыш будет явный я думаю)+ подготовленные запросы дают нам возможность не беспокоиться об экранировании. Поэтому лично мой выбор - везде использовать именно подготовленные запросы.

(Отредактировано автором: 28 Мая, 2014 - 12:27:55)

 
 Top
Anchor
Отправлено: 28 Мая, 2014 - 12:26:06
Post Id


Новичок


Покинул форум
Сообщений всего: 57
Дата рег-ции: Май 2014  


Помог: 0 раз(а)




Каков принцип работы плейсхолдеров? Я понимаю, если происходит подстановка строковых параметров. Тогда, да, как понимаю, там этот параметр, вылижут, отэкранируют, проверят, и пр. Со строковыми параметрами - безусловно удобнее.

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

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

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


Ведь 100% знаю, что $item_id теперь пролезет только ЧИСЛОВОЙ. Или все же есть нюансы и здесь?
 
 Top
caballero
Отправлено: 28 Мая, 2014 - 12:26:45
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




Цитата:
prepare используют не что бы повысить скорость, а что бы обезопасить свое приложение.
.
prepare не имеет никого отношения к биндингу параметров. Это разные ничем не связанные вещи.


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


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB