Edited at

PDO::ATTR_EMULATE_PREPARESのON/OFF比較

More than 1 year has passed since last update.


これを見るといい

PHPでデータベースに接続するときのまとめ

これ以上の簡潔な説明はない。


検証してみる


プリペアドステートメントのためにデータベースサーバと通信する必要が無くなるため,エミュレーションを行ったほうがパフォーマンスは向上する.


ということなので検証して差別化。


検証

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なので型が緩くて良いが、アプリだと型の不一致となって困る。