Има едно малко нещо за спомен. По подразбиране PDO просто имитира подготвени оператори.
И докато е в режим на емулация, той изпълнява същата стара заявка, без всъщност да подготвя нито едно изявление :)
И така, на първо място,
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
за да включите истински подготвени изявления.
Има още нещо, което трябва да се спомене.
За съжаление има много малко истински знания в света. И особено в света на сайтовете за въпроси и отговори. Хората са склонни да повтарят информацията, която са прочели и намират за разумна. Без да провеждат каквито и да било тестове за доказване или дори без да си поставят ръцете. Така че "често отбелязван" изобщо не трябва да се счита за надежден източник.
Обратно към въпроса:въпреки че трябва да има някакво наказание, то трябва да е незначително през повечето време. Ако е така - трябва да настроите системата си.
Както и да е, в режим на емулация го получихте едновременно "бързо" и безопасно.
Актуализиране
Е, след като изпълних вашите тестове върху моите данни, трябва да кажа, че нещо не е наред с вашата база данни, ако имате 3 пъти разлика в голям набор от данни.
За светкавична заявка
select title from Board where id = 1
резултатите са
emulation on off
query 0.07 0.130
prepare 0.075 0.145
докато за доста натоварващата заявка
select title from Board where id > 1
резултатите са
emulation on off
query 0.96 0.96
prepare 0.96 1.00
И така, както виждаме, при голям набор от данни разликата става незабележима.
За заявката за мълния има известна разлика, но тъй като отнема само 0,0003-та фракция от секундата (за една заявка) - бих казал, че това е идеалният пример за думата "безразличие".
За еднакви резултати между query()/prepare() - имам само една идея - PDO използва подготовка/изпълнение за всички заявки, дори тези без обвързване.
Сега към проблема с кодирането.
Да, странен проблем с GBK засяга PDO за версии преди 5.3.3. Тези версии нямаха начин да зададат правилното кодиране и бяха неизбежно уязвими (в режим на емулация). Но тъй като 5.3.3 PDO поддържа настройка на кодиране в DSN и сега всичко е наред с него.
За mysqli човек трябва да използва mysqli_set_charset()
за тази цел със същия (непроницаем) резултат.
В моя собствен клас, който е базиран на mysqli, използвам собствена реализация на заместител и изобщо не използвам подготвени изрази. Не от съображения за производителност, а за по-добра надеждност.