TOP比較データ> データベースへの接続を繰り返す

徹底比較!! PHP & Java

第2回:PHP4とJavaのパフォーマンス比較

著者:ワイズノット  土橋 芳孝   2004/11/24
前のページ  1  2  3
データベースへの接続を繰り返すテスト

  次はデータベースへの接続処理について実行速度の比較を行いたいと思います。実行速度を検証するプログラムとして、データベースへの接続を繰り返すプログラムを用意しました。そのプログラムでは、データベースへ接続するためのコネクションオブジェクトを10個取得し、それらのコネクションオブジェクトを利用してselect文を10回発行します。その後、それらのコネクションオブジェクトを解放します。このような動作を1000回繰り返している間の処理時間を測定することで、データベースへの接続における実行速度の比較を行っています。ソースコードと検証結果は下記をご覧ください。
PHP4版  データベースへの接続を繰り返すプログラム
<?php
list($sec1, $sec2) = explode(" ", microtime());
$start = $sec1 + $sec2;
echo 'start = '.$start.'<br>';

require_once 'DB.php';

for($i = 0; $i < 1000; $i++) {

// コネクションオブジェクトを10個取得する
list($sec1, $sec2) = explode(" ", microtime());
$start1 = $sec1 + $sec2;
$db = DB::connect('mysql://root@localhost/test');
$db1 = DB::connect('mysql://root@localhost/test');
$db2 = DB::connect('mysql://root@localhost/test');
$db3 = DB::connect('mysql://root@localhost/test');
$db4 = DB::connect('mysql://root@localhost/test');
$db5 = DB::connect('mysql://root@localhost/test');
$db6 = DB::connect('mysql://root@localhost/test');
$db7 = DB::connect('mysql://root@localhost/test');
$db8 = DB::connect('mysql://root@localhost/test');
$db9 = DB::connect('mysql://root@localhost/test');
if(DB::isError($db)) {
echo 'DBへの接続が失敗しました。';
}
list($sec1, $sec2) = explode(" ", microtime());
$end1 = $sec1 + $sec2;
$elapse1 += $end1 - $start1;

// select文を10回発行する
list($sec1, $sec2) = explode(" ", microtime());
$start2 = $sec1 + $sec2;
$result = $db->query
('select id, name from test_table order by id');
$result = $db1->query
('select id, name from test_table order by id');
$result = $db2->query
('select id, name from test_table order by id');
$result = $db3->query
('select id, name from test_table order by id');
$result = $db4->query
('select id, name from test_table order by id');
$result = $db5->query
('select id, name from test_table order by id');
$result = $db6->query
('select id, name from test_table order by id');
$result = $db7->query
('select id, name from test_table order by id');
$result = $db8->query
('select id, name from test_table order by id');
$result = $db9->query
('select id, name from test_table order by id');
if(DB::isError($result)) {
echo 'クエリーの実行が失敗しました。';
}
list($sec1, $sec2) = explode(" ", microtime());
$end2 = $sec1 + $sec2;
$elapse2 += $end2 - $start2;

// コネクションオブジェクトを10個解放する
list($sec1, $sec2) = explode(" ", microtime());
$start3 = $sec1 + $sec2;
$db->disconnect();
$db1->disconnect();
$db2->disconnect();
$db3->disconnect();
$db4->disconnect();
$db5->disconnect();
$db6->disconnect();
$db7->disconnect();
$db8->disconnect();
$db9->disconnect();
list($sec1, $sec2) = explode(" ", microtime());
$end3 = $sec1 + $sec2;
$elapse3 += $end3 - $start3;

}

list($sec1, $sec2) = explode(" ", microtime());
$end = $sec1 + $sec2;
echo 'end = '.$end.'<br>';

$elapse = $end - $start;
echo 'elapse = '.$elapse.'秒<br>';
echo 'elapse1 = '.$elapse1.'秒<br>';
echo 'elapse2 = '.$elapse2.'秒<br>';
echo 'elapse3 = '.$elapse3.'秒';
?>

Java(JSP)版  データベースへの接続を繰り返すプログラム
<%@ page contentType="text/html;charset=Shift_JIS" %>
<%@ page import="java.util.*,java.sql.*,javax.sql.*,javax.naming.*" %>
<%
long start = new java.util.Date().getTime();
long end = 0;
long start1 = 0;
long start2 = 0;
long start3 = 0;
long end1 = 0;
long end2 = 0;
long end3 = 0;
float elapse1 = 0;
float elapse2 = 0;
float elapse3 = 0;
InitialContext ic = null;
DataSource ds = null;
Connection con = null;
Connection con1 = null;
Connection con2 = null;
Connection con3 = null;
Connection con4 = null;
Connection con5 = null;
Connection con6 = null;
Connection con7 = null;
Connection con8 = null;
Connection con9 = null;
PreparedStatement ps = null;
ResultSet rs = null;
%>
start = <%=start%><br>
<%
for(int i = 0; i < 1000; i++) {
try {

// コネクションオブジェクトを10個取得する
start1 = new java.util.Date().getTime();
ic = new InitialContext();
ds = (DataSource)ic.lookup
("java:comp/env/jdbc/mysql");
con = ds.getConnection();
con1 = ds.getConnection();
con2 = ds.getConnection();
con3 = ds.getConnection();
con4 = ds.getConnection();
con5 = ds.getConnection();
con6 = ds.getConnection();
con7 = ds.getConnection();
con8 = ds.getConnection();
con9 = ds.getConnection();
end1 = new java.util.Date().getTime();
elapse1 += end1 - start1;

// select文を10回発行する
start2 = new java.util.Date().getTime();
ps = con.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con1.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con2.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con3.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con4.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con5.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con6.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con7.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con8.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
ps = con9.prepareStatement(
"select id, name from test_table order by id");
rs = ps.executeQuery();
end2 = new java.util.Date().getTime();
elapse2 += end2 - start2;

} catch(Exception e1) {
%>
<%=e1%><br> <%
} finally {
try {

// コネクションオブジェクトを10個解放する
start3 = new java.util.Date().getTime();
if(con != null) con.close();
if(con1 != null) con1.close();
if(con2 != null) con2.close();
if(con3 != null) con3.close();
if(con4 != null) con4.close();
if(con5 != null) con5.close();
if(con6 != null) con6.close();
if(con7 != null) con7.close();
if(con8 != null) con8.close();
if(con9 != null) con9.close();
end3 = new java.util.Date().getTime();
elapse3 += end3 - start3;

} catch(Exception e2) {
%>
<%=e2%><br>
<%
}
}
}
end = new java.util.Date().getTime();
%>
end = <%=end%><br>
elapse = <%=(float)(end - start) / 1000%>秒<br>
elapse1 = <%=(float)elapse1 / 1000%>秒<br>
elapse2 = <%=(float)elapse2 / 1000%>秒<br>
elapse3 = <%=(float)elapse3 / 1000%>秒

データベースへの接続を繰り返すプログラムの実行速度
  PHP4 Java
1回目 16.49秒 7.94秒
2回目 16.33秒 6.64秒
3回目 16.68秒 6.47秒
4回目 16.57秒 6.46秒
5回目 16.45秒 6.47秒
平均 16.50秒 6.80秒
  コネクション取得 select文発行 コネクション解放
PHP4 Java PHP4 Java PHP4 Java
1回目 11.12秒 1.90秒 5.03秒 3.76秒 0.24秒 2.28秒
2回目 11.01秒 1.09秒 4.99秒 3.37秒 0.23秒 2.15秒
3回目 11.36秒 1.09秒 4.97秒 3.42秒 0.25秒 1.94秒
4回目 11.23秒 1.22秒 5.00秒 3.22秒 0.24秒 2.02秒
5回目 11.11秒 1.15秒 5.00秒 3.34秒 0.24秒 1.97秒
合計 11.17秒 1.29秒 5.00秒 3.42秒 0.24秒 2.07秒

  以上のとおり、データベースへの接続処理についてもPHP4はJavaと比較して2分の1以下の実行速度であるという結果となりました。PHPはデータベースと連携する高速なWebアプリケーションを開発できる言語として脚光を浴びておりますが、PHP4では高性能なJavaに追いつくことができないようです。


コネクションプールの優位性

  このような結果が出た大きな原因として、コネクションプールの存在が考えられます。コネクションプールとは、データベースに接続するためのオブジェクトであるコネクションオブジェクトを素早く取り出せるようにしておく仕組みのことです。コネクションオブジェクトの取得には時間がかかるため、あらかじめ素早く取り出せる場所に必要な数だけコネクションオブジェクトをプールしておくことで、データベース接続の際の実行速度を向上させています。


  今回利用したTomcat(Java Servlet/JSPコンテナ)には、DBCPといわれるコネクションプールが搭載されています。一方、PHP4ではコネクションプールを利用することができません(※1)。その違いが、コネクションオブジェクトを取得する際に10倍程度の実行速度の差(PHP4:11.17秒、Java:1.29秒)となってあらわれていることは間違いないでしょう。

  ここまでPHP4とJavaのパフォーマンスを比較してきました。現在の企業システムは、その重要度を増し、扱うデータ量も増大する一方です。処理は多様化・複雑化し、多くのデータベースや外部システムとの連携が必要となっています。そのような状況にあって、より多くのデータを処理しなければならない大規模システムにPHP4を導入することは難しいと言わざるおえません。PHPは小規模なWebアプリケーション向けの開発言語と言われますが、その理由のひとつとしてPHP4のパフォーマンス面に起因することは否めないでしょう。

※1 今回はデータベースとしてMySQLを利用しているため検証はできませんでしたが、PHPでコネクションプールを利用したい場合、データベースにPostgreSQLを利用するという方法があります。PostgreSQLにはpgpoolというコネクションプールサーバーがあるため、PHPとPostgreSQLの組み合わせでコネクションプールを実現可能です。

  第3回では、PHP4とJavaのオブジェクト指向について比較し、それぞれの言語の適用分野を検証していきます。

前のページ  1  2  3



著者プロフィール
株式会社ワイズノット  土橋 芳孝
以前はJavaを利用したWebアプリケーション開発とオブジェクト指向設計を得意としていたが、ワイズノットに入社以来、PHPの魅力にとりつかれる。現在はワイズノットのプロジェクトマネージャーとして、PHPをはじめとしたオープンソースの普及に力を注いでいる。


INDEX
第2回:PHP4とJavaのパフォーマンス比較
  動作環境
  5000までの素数を表示させる
データベースへの接続を繰り返す