これを見るといい
これ以上の簡潔な説明はない。
検証してみる
プリペアドステートメントのためにデータベースサーバと通信する必要が無くなるため,エミュレーションを行ったほうがパフォーマンスは向上する.
ということなので検証して差別化。
検証
PHP 7.1 と MySQL 5.7 です。
<?php
class FetchClass {
public $id;
public $varchar_1;
public $text_1;
public $int_1;
public $int_2;
public $int_3;
public $timestamp_1;
public $timestamp_2;
}
function profile($emulates) {
$pdo = new PDO('mysql:host=localhost;dbname=any_db', 'root', 'pass');
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, $emulates);
$start = microtime(true);
foreach(range(0, 9999) as $i){
$id = 1000000 + $i;
$st = $pdo->prepare('select id, varchar_1, text_1, int_1, int_2, int_3, timestamp_1, timestamp_2 from any_table where id = ?');
$st->setFetchMode(PDO::FETCH_CLASS, 'FetchClass');
$st->bindParam(1, $id);
$st->execute();
$rows = $st->fetchall();
}
return microtime(true) - $start;
}
$on_time = profile(true);
$off_time = profile(false);
echo "emulate on : time : $on_time";
echo "emulate off : time : $off_time";
結果
emulate on : time : 0.87435293197632
emulate off : time : 1.4851009845734
今回の計測では約1.7倍の差。かなりエミュレートモードが早い!
なので一概に「エミュレートモードをOFFにしよう」にはならない。
検索結果の型情報
MySQLではエミュレートモードを使うと検索結果の型情報が失われる。
検索結果をvar_export()
したものがこちら。
-- emulate on : 全部文字列 --
FetchClass::__set_state(array(
'id' => '1000000',
'varchar_1' => 'name',
'text_1' => 'comment',
'int_1' => '1',
'int_2' => '155',
'int_3' => '161',
'timestamp_1' => '2017-12-13 11:28:09',
'timestamp_2' => '2017-12-13 11:28:09',
))
-- emulate off : カラムの型通り --
FetchClass::__set_state(array(
'id' => 1000000,
'varchar_1' => 'name',
'text_1' => 'comment',
'int_1' => 1,
'int_2' => 155,
'int_3' => 161,
'timestamp_1' => '2017-12-13 11:28:09',
'timestamp_2' => '2017-12-13 11:28:09',
))
これをjson_encode()
して、ブラウザやアプリに渡すこともあると思うが
ブラウザはJavaScriptなので型が緩くて良いが、アプリだと型の不一致となって困る。