PDO、PEAR::DB、MySQL関数の速度比較
2007年04月07日 プログラミングTIPS
PHPからデータベースを扱うことは良くあります。
その際、一体どういった方法でデータベースを扱うのが一番優れているのか、けっこう悩むところでもあります。
PHP4の頃までは、抽象化してデータベースを扱うために、PEAR::DBやPEAR::MDBなどが多く使われていました。
PHP5になってから、最近では速度面で有利とされるPDOが流行っています。
簡単な処理速度比較などを載せているサイトもありますが、「PHP用アクセラレータ」導入済みでの比較結果はあまり載っていません。
自分で扱っているサーバーと似たような構成での処理速度比較でないと、速度比較の信頼性も落ちます。
そこで、今回はPHP5.2.1とeAcceleratorをインストールしているサーバーで実際にPDO、PEAR::DB、ネイティブのMySQL関数の速度比較を行ってみました。
その際、一体どういった方法でデータベースを扱うのが一番優れているのか、けっこう悩むところでもあります。
PHP4の頃までは、抽象化してデータベースを扱うために、PEAR::DBやPEAR::MDBなどが多く使われていました。
PHP5になってから、最近では速度面で有利とされるPDOが流行っています。
簡単な処理速度比較などを載せているサイトもありますが、「PHP用アクセラレータ」導入済みでの比較結果はあまり載っていません。
自分で扱っているサーバーと似たような構成での処理速度比較でないと、速度比較の信頼性も落ちます。
そこで、今回はPHP5.2.1とeAcceleratorをインストールしているサーバーで実際にPDO、PEAR::DB、ネイティブのMySQL関数の速度比較を行ってみました。
実験環境
実験をしたサーバーの環境は、下表の通りです。環境 | バージョン |
---|---|
OS | CentOS4 |
PHP | 5.2.1 |
PHPアクセラレータ | eAccelerator0.9.5 |
MySQL | 4.1 |
PEAR::DB | 1.7.11 |
また、データベースの処理速度比較をする上で、今回は実運用面で比較対象としやすい、当ブログ「[Z]ZAPAブロ~グ2.0」のエントリデータを対象としました。
たまに、「10件しか存在しないDBから10件取得する」比較を行っているサイトもあったりしますが、件数が少なすぎても、あまり信頼性が高くありません。
2004年7月から投稿し続け、エントリが1000件弱存在する当ブログのDBを対象としました。
実験方法
実験方法は、以下のようにしました。1.MySQLデータベースに接続するこの処理にかかる時間を、PDO 関数、PEAR::DBとネイティブ関数であるMySQL関数、MySQLi関数でそれぞれ計測してみました。
2.[Z]ZAPAブロ~グ2.0の全1000件弱のエントリデータから全件取得する
3.全エントリ本文を変数に代入する
4.データベースから切断する
一つのスクリプト内で、それぞれの方法でMySQLサーバーに接続して、それぞれSQL文を発行し、MySQLサーバーから切断しました。
また、キャッシュの効果を測定するために、同スクリプト内で同じSQL文を2回発行し、計8回DB接続、クエリ発行、DB切断を行いました。
(mysqli→pdo→pear::DB→mysql→mysqli(2)→pdo(2)→pear::DB(2)→mysql(2)の順番です)
実験結果
実験結果は、下表の通りです。(キャッシュの効果を測定するために、同スクリプト内で同じSQL文を2回発行し、(2)としています)
ブログ全データ(約千件)をSELECTしたときにかかった秒数 | |||||
---|---|---|---|---|---|
処理方法 | 1回目 | 2回目 | 3回目 | 4回目 | 5回目 |
mysqli: | 0.00892秒 | 0.00902秒 | 0.00885秒 | 0.00875秒 | 0.00905秒 |
pdo: | 0.01536秒 | 0.01416秒 | 0.01570秒 | 0.01369秒 | 0.01370秒 |
pear::DB: | 0.02275秒 | 0.02669秒 | 0.02460秒 | 0.02257秒 | 0.02260秒 |
mysql: | 0.01065秒 | 0.01118秒 | 0.01066秒 | 0.05339秒 | 0.01064秒 |
mysqli(2): | 0.00914秒 | 0.01039秒 | 0.00911秒 | 0.00905秒 | 0.00938秒 |
pdo(2): | 0.00044秒 | 0.00045秒 | 0.00037秒 | 0.00034秒 | 0.00088秒 |
pear::DB(2): | 0.01989秒 | 0.02007秒 | 0.02300秒 | 0.02003秒 | 0.02123秒 |
mysql(2): | 0.00943秒 | 0.01047秒 | 0.00953秒 | 0.00962秒 | 0.00942秒 |
サーバー側の問題もあるので、毎回安定した処理結果は得られませんでしたが、大体上表のような結果になりました。
やはりネイティブ関数は速く、mysqli関数が一番速い結果になりました。
続いて同じくネイティブ関数のmysql関数が続き、その次にPDOという結果になりました。
PDOでは、プリペアドステートメントを用いてSQLを発行したため、2回目のSQLの発行ではキャッシュが効き、劇的な速さになっています。
一番遅かったのは予想通り、PEAR::DBでした。
ネイティブ関数よりも2〜3倍遅く、PDOよりも2倍近く遅い結果となりました。
PHP用アクセラレータを導入していなければ、PEAR::DBはもっと遅くなっただろうと考えられます。
まとめ
PHP5を利用していて、DBの抽象化を行いたいのであれば、PEAR系のモジュールはやめてPDOにした方が良いと言えます。単純なSELECT文の結果でさえ、2倍近い性能差が出ていますから当然です。
DBの抽象化を行う必要がない場合、PDOを使うかネイティブ関数を使うか迷うところですが、状況に応じて使い分けるのが良いと思います。
PDOは、対象データベースがMySQL 3.x/4.x/5.xを始め、PostgreSQL、SQLite 3、SQLite 2、FreeTDS、Microsoft SQL Server、Sybase、Firebird/Interbase 6、IBM DB2、Oracle Call Interfaceなどの大量のデータベースに対応しています。
他のDBも扱う予定があるのならば、PDOの処理だけを覚えてしまうのが簡単です。
一方、処理速度がボトルネックとなっていて、DBを変更する予定もないのであればネイティブ関数のmysqli関数でチューニングするという方向で良いと思います。
PDOは、PEAR::DBのように圧倒的に遅いわけではないので、状況に応じて選べば良いと思います。
当然、そのサーバーで扱うデータを元に、それぞれのSQLを発行して処理速度比較を計測してから決めることも重要です。
PHP5系の利点として、SimpleXML関数を使えるのが個人的に一番利点だと思っていましたが、今回の実験によりPDO 関数が使えるのも大きな利点だということがわかりました。
追記:PHP7以降の情報は「PHPでデータベースに接続するときのまとめ - Qiita」を読んでください。非常に良くまとまっています。