MongoDB,CouchDB,MySQL,memcacheデータをPHPから読み込み&書き込み速度を検証してみました!

前回、前前回とMongoDB,CouchDBのインストール方法やphpからの使用方法を記事にしました。
CentOS5.4にCouchDBをインストールする方法! - @camelmasaの開発日記
CouchDBをphpから操作する方法。 - @camelmasaの開発日記
CentOS5.4にMongoDBをインストールする方法! - @camelmasaの開発日記
MongoDBをphpから操作する方法。 - @camelmasaの開発日記

MongoDBとCouchDBMySQL(MyISAM)とmemcacheを加えて読み込み(SELECT)と書き込み(INSERT)の速度を検証してみたいと思います。


環境

OS:CentOS5.4
PHP:5.3.1
MongoDB:1.2.2
CouchDB:0.10.1
MySQL:5.1.43
memcache:1.2.8

CPU:AMD(の何か)
メモリ:4GB
(ざっくりと検証です。)


読み取り時のソース

簡単に、"test"データベースの"test"テーブル(コレクション)の"test"データをphpから読み込みするプログラムです。
こんなソースで良いのか。


couchdb.php

<?php

require_once "HTTP/Request.php";

$http = new HTTP_Request('http://192.168.80.139:5984/test/93e4b62c166489b5ff94600e3003db88');
$response = $http->sendRequest();

mongodb.php

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$cursor = $col->findOne();

mysql.php

<?php
$link = mysql_pconnect('localhost', 'user', 'pass');
mysql_select_db('mytest', $link);
$result = mysql_query('SELECT `test` FROM `test`;');

memcache.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->get('test');

読み込み結果

couchdb.php

ab -c 100 -n 1000 'http://192.168.0.30/couchdb.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /couchdb.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   9.587989 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    104.30 [#/sec] (mean)
Time per request:       958.799 [ms] (mean)
Time per request:       9.588 [ms] (mean, across all concurrent requests)
Transfer rate:          19.29 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.5      0       9
Processing:    22  926 923.1    650    9554
Waiting:       21  860 568.4    650    5877
Total:         22  927 923.5    650    9555

Percentage of the requests served within a certain time (ms)
  50%    650
  66%    662
  75%    783
  80%   1099
  90%   1565
  95%   1735
  98%   3220
  99%   5656
 100%   9555 (longest request)


mongodb.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.939626 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    515.56 [#/sec] (mean)
Time per request:       193.963 [ms] (mean)
Time per request:       1.940 [ms] (mean, across all concurrent requests)
Transfer rate:          95.38 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.5      0       8
Processing:    35  187  35.4    201     236
Waiting:       35  187  35.4    201     235
Total:         35  187  35.2    201     244

Percentage of the requests served within a certain time (ms)
  50%    201
  66%    202
  75%    204
  80%    204
  90%    207
  95%    208
  98%    209
  99%    226
 100%    244 (longest request)


mysql.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.421236 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    703.61 [#/sec] (mean)
Time per request:       142.124 [ms] (mean)
Time per request:       1.421 [ms] (mean, across all concurrent requests)
Transfer rate:          130.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   5.1      0      22
Processing:     7  131 142.4    129    1404
Waiting:        7  131 142.3    129    1403
Total:         19  133 142.6    129    1416

Percentage of the requests served within a certain time (ms)
  50%    129
  66%    130
  75%    136
  80%    138
  90%    141
  95%    144
  98%    173
  99%   1339
 100%   1416 (longest request)


memcache.php

ab -c 100 -n 1000 'http://192.168.0.30/memcache.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.453866 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      191900 bytes
HTML transferred:       0 bytes
Requests per second:    687.82 [#/sec] (mean)
Time per request:       145.387 [ms] (mean)
Time per request:       1.454 [ms] (mean, across all concurrent requests)
Transfer rate:          128.62 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   15  10.2     14      45
Processing:    20  124  36.9    138     479
Waiting:       16  109  35.7    119     462
Total:         27  139  41.8    147     496

Percentage of the requests served within a certain time (ms)
  50%    147
  66%    163
  75%    172
  80%    176
  90%    186
  95%    191
  98%    198
  99%    203
 100%    496 (longest request)

読み込み結果検証

Requests per secondの順位下記。
MySQL(MyISAM)>memcache>MongoDB>>>CouchDB

MySQLが一番早い結果になるとは思わなかったです。(なって欲しくなかった)
でもFacebookでのMySQL運用術はKVSの様にシンプルなのかな。
(http://hyuki.com/yukiwiki/wiki.cgi?HowFriendFeedUsesMySqlToStoreSchemaLessData)

CouchDBはRESTでのデータ取得をPEARでやってしまってるので遅いのかな?
毎度毎度その処理部分のPHPコンパイルする分遅くなっているのでしょう。

MongoDBもmemcache並に早いですね。
MySQLがmemcacheより早いのは意外です。解せぬ〜。

次は書き込み時の速さを見てみます。


書き込み時のソース

couchdbはinsertの方法が調べれず…><
誰か教えて!ヘルプ!


mongodb_write.php

<?php

$mongo = new Mongo();

$db = $mongo->selectDB("test");
$col = $db->selectCollection("test");
$col->insert(array("test" => "test"));


mysql_write.php

<?php
        $link = mysql_pconnect('localhost', 'root', '');
        mysql_select_db('mytest', $link);
        $result = mysql_query("INSERT INTO `test` VALUES ('test');");


memcache_write.php

<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$memcache->set("test", "test");

書き込み結果

mongodb_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mongodb_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mongodb_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   9.325888 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190190 bytes
HTML transferred:       0 bytes
Requests per second:    107.23 [#/sec] (mean)
Time per request:       932.589 [ms] (mean)
Time per request:       9.326 [ms] (mean, across all concurrent requests)
Transfer rate:          19.84 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    4   9.7      0      36
Processing:    30  728 1111.7    176    9092
Waiting:        3  725 1112.6    176    9091
Total:         31  732 1111.0    177    9108

Percentage of the requests served within a certain time (ms)
  50%    177
  66%    910
  75%    937
  80%    938
  90%   1030
  95%   3103
  98%   3148
  99%   4285
 100%   9108 (longest request)


mysql_write.php

ab -c 100 -n 1000 'http://192.168.0.30/mysql_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /mysql_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.484070 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190000 bytes
HTML transferred:       0 bytes
Requests per second:    673.82 [#/sec] (mean)
Time per request:       148.407 [ms] (mean)
Time per request:       1.484 [ms] (mean, across all concurrent requests)
Transfer rate:          124.66 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.6      0       8
Processing:    41  142 165.8    129    1478
Waiting:       40  142 165.8    129    1478
Total:         41  143 165.8    129    1479

Percentage of the requests served within a certain time (ms)
  50%    129
  66%    131
  75%    132
  80%    133
  90%    139
  95%    144
  98%    161
  99%   1476
 100%   1479 (longest request)


memcache_write.php

ab -c 100 -n 1000 'http://192.168.0.30/memcache_write.php'

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.30 (be patient)


Server Software:        Apache/2.2.3
Server Hostname:        192.168.0.30
Server Port:            80

Document Path:          /memcache_write.php
Document Length:        0 bytes

Concurrency Level:      100
Time taken for tests:   1.701421 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      190380 bytes
HTML transferred:       0 bytes
Requests per second:    587.74 [#/sec] (mean)
Time per request:       170.142 [ms] (mean)
Time per request:       1.701 [ms] (mean, across all concurrent requests)
Transfer rate:          108.73 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   17  11.0     18      44
Processing:    34  143  24.8    148     267
Waiting:        3  126  25.6    132     261
Total:         34  160  28.3    163     301

Percentage of the requests served within a certain time (ms)
  50%    163
  66%    175
  75%    181
  80%    185
  90%    192
  95%    195
  98%    201
  99%    205
 100%    301 (longest request)

全体を通したまとめ

大分ざっくりとした検証で納得がいくのかわかりませんが個人的には概ね満足。
インストール〜設定〜動作等で見えた部分は勉強になりました。

検証前は圧倒的にmemcacheが一番早いだろうと思ったのですが、読み書きともMySQLとほぼ同じ位で驚きました。
その後僅差でMongoDB。
CouchDBはhttp通信をphpでしてしまってるので良い結果が得られなかった感じですか。
(couchdb.so作って!)

恐らく皆さんが書いているように、RDBMSも単体では速度的に問題なくて、複雑なSQLを処理しようとするとボトルネックになるのでしょうか。
スケーリングを意識したSQLを書く事で、KVS並に高速化になるのかもしれません。
参考:http://hyuki.com/yukiwiki/wiki.cgi?HowFriendFeedUsesMySqlToStoreSchemaLessData


あとがき

うーん…。
こうしたらMongoDBが早くなるよ!的なアドバイス欲しいな〜。

上記のテストサーバーは家でそのままにしてあるので、こんなテストして!っていう場合コメント下さい。
テストしてブログに書きます。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

Oracle OpenWorld Tokyo 2009 1日目に参加しました。&アンカンファレンスで講演をしました!

昨日Oracle OpenWorld Tokyo 2009 1日目に参加しました。
そしてアンカンファレンスで講演をしました!

Oracle OpenWorld Tokyo 2009 1日目午前

Oracle OpenWorld Tokyo 2009 1日目午前中は、私のアンカンファレンスでの講演がありましたので、自分の準備で精一杯でした。


※後日slideshareYouTubeにてプレゼンテーションの様子をアップロードしたいと思います。

福岡さんが私のアンカンファレンスの記事の感想を書いてくれました!
感激!
camelmasaさんのUnconferenceが終了: DFJJ

Oracle OpenWorld Tokyo 2009 1日目午後

午後〜夕方は知人と会ってまして、それからもとくんβさんのアンカンファレンスを聞きました。

もとくんβさんのアンカンファレンスで学んだことは

  • Oracle Database XEとRubyの相性が良い
  • 自分を売り込む色々な方法がある事

を学びました。
また、CDでBICSというエクセルのマクロで簡単にマニュアルが作成出来るツールを頂きました。

アンカンファレンス後、挨拶に行ったところ「名刺はフリーエンジニアにとってとても大事なもの」と教えて頂きました。
私は金銭面から手作りで名刺を作成しているのですが、どうしても家のプリンターでは綺麗に印刷できないんですね。
どうにか綺麗に印刷する方法を考えるか、早く名刺をオリジナルで作成できるほどの経済力を身につけるかですかね(笑)


18:30からはMr円で有名な早稲田大学教授榊原さんの「世界同時不況下での経営」という特別講演を聞きました。
榊原英資 - Wikipedia

世界同時不況は構造的な問題なので、まだまだ状況は悪くなる可能性があるそうです。


Oracle OpenWorld Tokyo 2009 1日目を終えて

様々なエンジニアの方とお知り合いになれた事がとても嬉しい一日でした。

一番驚きなのが、私がアンカンファレンスという機会を頂いてエンジニアの皆さんにプレゼンテーションしたことです。
私がエンジニアに向けて技術の話をする事なんて、昨年の私は想像も出来ませんでした。
一皮剥けた感じがします。
この様な機会を与えてくれたオラクル社に感謝したいと思います!
有難うございました!



[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。Oracle Database XE編

MySQLのコネクションプーリングは約2倍の性能結果が出ました。(同時100接続で100万回リクエストのApache Benchを実行した場合)

Oracle Database XEでのコネクションプーリングはどうでしょうか?検証してみたいと思います。


まずはOracle Database XEのコネクションプーリングしない方法で検証です。

コネクションプーリングしないプログラムで100万回リクエストのApache Benchを実行

下記のスクリプトを実行
oracle_connect.php

<?php
  $link = oci_connect('system', '[パスワード]', 'xe');
  $result = oci_parse($link, "SELECT 1;");
  oci_close($link);
?>

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/oracle_connect.php 

Apache Benchの実行結果

[root@www html]# ab -n 1000000 -c 100 http://localhost/oracle_connect.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /oracle_connect.php
Document Length: 0 bytes

Concurrency Level: 100
Time taken for tests: 1259.278234 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 190000000 bytes
HTML transferred: 0 bytes
Requests per second: 794.11 [#/sec] (mean)
Time per request: 125.928 [ms] (mean)
Time per request: 1.259 [ms] (mean, across all concurrent requests)
Transfer rate: 147.34 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 18.5 0 691
Processing: 0 122 249.2 61 9350
Waiting: 0 115 238.9 61 9349
Total: 0 125 251.4 61 9350

Percentage of the requests served within a certain time (ms)
50% 61
66% 63
75% 77
80% 100
90% 208
95% 383
98% 907
99% 1378
100% 9350 (longest request)

Time taken for tests: 1259.278234 secondsなので、約21分かかりました。
かなり遅い結果ですねー…。

逆にコネクションプーリングした際とどれ位差があるのか気になります。


コネクションプーリングの検証をする前に気になった記事がありましたのでこちらも検証しました。

oci_pconnectの第4引数を指定するとパフォーマンス向上 - Do You PHP はてブロ


コネクションプーリングしないプログラムで100万回リクエストのApache Benchを実行(接続時キャラクタセットを指定)

下記のスクリプトを実行
oracle_connect2.php

<?php
  $link = oci_connect('system', '[パスワード]', 'xe', 'JA16SJIS');
  $result = oci_parse($link, "SELECT 1;");
  oci_close($link);
?>

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/oracle_connect2.php 

Apache Benchの実行結果

[root@www html]# ab -n 1000000 -c 100 http://localhost/oracle_connect2.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /oracle_connect2.php
Document Length: 0 bytes

Concurrency Level: 100
Time taken for tests: 1176.803295 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 190000000 bytes
HTML transferred: 0 bytes
Requests per second: 849.76 [#/sec] (mean)
Time per request: 117.680 [ms] (mean)
Time per request: 1.177 [ms] (mean, across all concurrent requests)
Transfer rate: 157.67 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 21.7 0 609
Processing: 0 113 227.8 54 7051
Waiting: 0 104 213.3 54 7050
Total: 0 117 231.5 54 7051

Percentage of the requests served within a certain time (ms)
50% 54
66% 57
75% 75
80% 92
90% 209
95% 376
98% 765
99% 1358
100% 7051 (longest request)

Time taken for tests: 1176.803295 secondsなので、約20分かかりました。
さほど変わらず遅いですが、id:shimookaさんの記事の通り少し早くなりましたね。


次にOracle Database XEのコネクションプーリングの検証をしたいと思います!

コネクションプーリングするプログラムで100万回リクエストのApache Benchを実行

下記のスクリプトを実行
oracle_pconnect.php

<?php
  $link = oci_pconnect('system', '[パスワード]', 'xe');
  $result = oci_parse($link, "SELECT 1;");
  oci_close($link);
?>

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/oracle_pconnect.php 

Apache Benchの実行結果

[root@www html]# ab -n 1000000 -c 100 http://localhost/oracle_pconnect.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /oracle_pconnect.php
Document Length: 0 bytes

Concurrency Level: 100
Time taken for tests: 505.614765 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 190001710 bytes
HTML transferred: 0 bytes
Requests per second: 1977.79 [#/sec] (mean)
Time per request: 50.561 [ms] (mean)
Time per request: 0.506 [ms] (mean, across all concurrent requests)
Transfer rate: 366.98 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 5 10.3 1 319
Processing: 0 44 127.2 24 8470
Waiting: 0 33 117.1 12 8460
Total: 0 49 128.9 28 8476

Percentage of the requests served within a certain time (ms)
50% 28
66% 58
75% 61
80% 63
90% 83
95% 103
98% 189
99% 455
100% 8476 (longest request)

Time taken for tests: 505.614765 secondsなので、約8分かかりました。
約2倍強処理速度が向上しました。

コネクションプーリングするプログラムで100万回リクエストのApache Benchを実行(接続時キャラクタセットを指定)

下記のスクリプトを実行
oracle_pconnect2.php

<?php
  $link = oci_pconnect('system', '[パスワード]', 'xe', 'JA16SJIS');
  $result = oci_parse($link, "SELECT 1;");
  oci_close($link);
?>

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/oracle_pconnect2.php 

Apache Benchの実行結果

[root@www html]# ab -n 1000000 -c 100 http://localhost/oracle_pconnect2.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /oracle_pconnect2.php
Document Length: 0 bytes

Concurrency Level: 100
Time taken for tests: 380.586453 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 190000190 bytes
HTML transferred: 0 bytes
Requests per second: 2627.52 [#/sec] (mean)
Time per request: 38.059 [ms] (mean)
Time per request: 0.381 [ms] (mean, across all concurrent requests)
Transfer rate: 487.53 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 8.6 0 297
Processing: 0 33 122.2 5 6322
Waiting: 0 25 114.2 3 6321
Total: 0 37 123.7 6 6325

Percentage of the requests served within a certain time (ms)
50% 6
66% 47
75% 52
80% 54
90% 65
95% 87
98% 138
99% 379
100% 6325 (longest request)

Time taken for tests: 380.586453 secondsなので、約6分かかりました。
こちらも約2倍強処理速度が向上しました。
コネクションプーリングをしないMySQL並に速度が向上した結果が出ました。

まとめ

処理速度はやはりMySQLに分がありますね。さすがです。
しかし、無償のOracle Database XEをコネクションプーリングをする事で、同時接続時の処理速度の向上が図れる事がわかりました。
これを知る事・体験する事が出来て良い検証だったなーと思いました。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。MySQL編 その3

前回の検証では、コネクションプーリングの利点を理解する事が出来たのですが、Apache Benchでの検証をするとどうなるかというコメントで終了していました。
今回Apache Benchでの検証をしたいと思います。


phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。MySQL編 - @camelmasaの開発日記


phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。MySQL編 その2 - @camelmasaの開発日記

mysql_connect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続しない場合)

mysql_connect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  $link = mysql_connect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  for($i=0;$i<1000000;$i++){
    $result = mysql_query("SELECT 1;");
  }
  mysql_close($link);

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

このスクリプトを下記に修正。
mysql_connect2.php

<?php
  $link = mysql_connect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  $result = mysql_query("SELECT 1;");
  mysql_close($link);
?>

上記のコネクションプーリングしないプログラムで100万回リクエストのApache Benchを実行

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/mysql_connect2.php

Apache Benchの実行結果

[root@www time2]# ab -n 1000000 -c 100 http://localhost/mysql_connect2.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /mysql_connect2.php
Document Length: 1 bytes

Concurrency Level: 100
Time taken for tests: 364.58800 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 191000000 bytes
HTML transferred: 1000000 bytes
Requests per second: 2746.81 [#/sec] (mean)
Time per request: 36.406 [ms] (mean)
Time per request: 0.364 [ms] (mean, across all concurrent requests)
Transfer rate: 512.34 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 14.0 0 347
Processing: 0 33 140.2 4 7507
Waiting: 0 25 100.9 3 7486
Total: 0 35 143.5 4 7507

Percentage of the requests served within a certain time (ms)
50% 4
66% 9
75% 15
80% 22
90% 99
95% 192
98% 302
99% 394
100% 7507 (longest request)

Time taken for tests: 364.58800 secondsと出力されているので、6分以上かかった事になります。
結構かかりますね。

mysql_pconnect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続しない場合)

mysql_pconnect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  $link = mysql_pconnect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  for($i=0;$i<1000000;$i++){
    $result = mysql_query("SELECT 1;");
  }
  //mysql_close($link);

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

このスクリプトを下記に修正。

mysql_pconnect2.php

<?php
  $link = mysql_pconnect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  $result = mysql_query("SELECT 1;");
?>

for文部分を外して上記のコネクションプーリングをしたプログラムでApache Benchを実行しました。

上記のコネクションプーリングをするプログラムで100万回リクエストのApache Benchを実行

Apache Benchの実行

ab -n 1000000 -c 100 http://localhost/mysql_pconnect2.php

Apache Benchの実行結果

[root@www time2]# ab -n 1000000 -c 100 http://localhost/mysql_pconnect2.php
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100000 requests
Completed 200000 requests
Completed 300000 requests
Completed 400000 requests
Completed 500000 requests
Completed 600000 requests
Completed 700000 requests
Completed 800000 requests
Completed 900000 requests
Finished 1000000 requests


Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80

Document Path: /mysql_pconnect2.php
Document Length: 1 bytes

Concurrency Level: 100
Time taken for tests: 195.267289 seconds
Complete requests: 1000000
Failed requests: 0
Write errors: 0
Total transferred: 191000000 bytes
HTML transferred: 1000000 bytes
Requests per second: 5121.19 [#/sec] (mean)
Time per request: 19.527 [ms] (mean)
Time per request: 0.195 [ms] (mean, across all concurrent requests)
Transfer rate: 955.22 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 3.4 0 235
Processing: 0 18 43.3 14 2793
Waiting: 0 14 23.2 13 2480
Total: 0 19 43.6 15 2793

Percentage of the requests served within a certain time (ms)
50% 15
66% 17
75% 19
80% 20
90% 24
95% 30
98% 61
99% 114
100% 2793 (longest request)

Time taken for tests: 195.267289 secondsと出力されているので、3分以上かかった事になります。

まとめ

コネクションプーリングをした方が約2倍早く終了しました。
http接続等で同時接続が沢山ある時はコネクションプーリングはかなり効果的なのがわかりました。
今後MySQLを使用したアプリケーションを作成する時は、コネクションプーリングも考慮しようと思います。

次こそはphp + Oracle Database XEのコネクションプーリングを検証したいと思います!



[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。MySQL編 その2

前回の記事の検証では、いまいちコネクションプーリング自体を理解していない状態での検証でした。
その為、良い結果を出す事が出来ませんでしたので再度挑戦しました。

前回の記事
http://d.hatena.ne.jp/camelmasa/20090225/1235515758

コネクションプーリングの利点が引き出せなかった原因

  • ディスク上に書き込みが発生してしまうINSERTクエリを発行していた。
  • execでphpを実行した為

id:sh2さんコメント有難う御座います。



また、mixiにてさぁやさんからもご指摘を頂きました。

MySQLコミュニティ
http://mixi.jp/view_bbs.pl?id=40155421&comment_count=2&comm_id=2234

コメントもあったようですが,exec で php プロセスを毎回立ち上げては,pconnect を使ってないのと一緒ですよね

単純に,

for(;;) {
$dbh = mysql_pconnect(...);
}

という場合と,

for(;;) {
$dbh = mysql_connect();
mysql_close($dbh);
}

のコードで比べてみてはいかがでしょうか?

なるほど。
僕は『スクリプトの実行が終了してもMySQLとの接続が閉じられないということ』という事でexec関数で1万回phpスクリプトを実行してしまいました。そういう意味では無いという事ですね。

さぁやさん有難う御座いました。

さぁやさんのmixi
http://mixi.jp/show_friend.pl?id=379328



前回の反省を踏まえ、スクリプトSQL部分を、書き込みが発生しないSELECTクエリに変更し、さぁやさんが提供して頂いたソースで検証してみたいと思います。
また、for文内でMySQLに毎回接続しない方法でも検証してみたいと思います。

mysql_connect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続)

mysql_connect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  for($i=0;$i<1000000;$i++){
    $link = mysql_connect('localhost', 'root', '[パスワード]');
    mysql_select_db('mysql_connect', $link);
    $result = mysql_query("SELECT 1;");
    mysql_close($link);
  }

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

実行結果

  • 137.99708008766
  • 127.38695812225
  • 141.63528704643
  • 133.98114085197
  • 142.13206601143

平均130秒程度といった結果でした。


mysql_pconnect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続)

mysql_pconnect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  for($i=0;$i<1000000;$i++){
    $link = mysql_pconnect('localhost', 'root', '[パスワード]');
    mysql_select_db('mysql_connect', $link);
    $result = mysql_query("SELECT 1;");
    //mysql_close($link);
  }

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

実行結果

  • 78.858249902725
  • 62.917754888535
  • 59.676470994949
  • 76.271098852158
  • 65.784828901291

平均70秒程度といった結果でした。


mysql_connect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続しない場合)

mysql_connect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  $link = mysql_connect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  for($i=0;$i<1000000;$i++){
    $result = mysql_query("SELECT 1;");
  }
  mysql_close($link);

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

実行結果

  • 26.621978998184
  • 27.744408845901
  • 27.353181123734
  • 22.033998966217
  • 21.772191047668

平均24秒程度といった結果でした。


mysql_pconnect関数でSELECTクエリ100万回の速度実験(for文内でMySQLに毎回接続しない場合)

mysql_pconnect.php

<?php
  $start = array_sum(explode(" ",microtime()));

  $link = mysql_pconnect('localhost', 'root', '[パスワード]');
  mysql_select_db('mysql_connect', $link);
  for($i=0;$i<1000000;$i++){
    $result = mysql_query("SELECT 1;");
  }
  //mysql_close($link);

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

実行結果

  • 21.91073012352
  • 28.815995931625
  • 21.802286863327
  • 26.527863025665
  • 24.077289104462

こちらも平均24秒程度といった結果でした。

まとめ

for文内等でMySQLに毎回接続しなくてはいけないケース(どうゆうケースか想定出来ませんが…)php + MySQLでのコネクションプーリングの利点を確認する事が出来ました。
しかし、for文内でMySQLの接続をする必要が無ければ、コネクションプーリングする必要性が無いという結果が出ました。



次こそはphp + Oracle Database XEのコネクションプーリングを検証したいと思います!

[追記]
次回もid:sh2さんやmixiでのさぁやさんからご指摘を頂きab (Apache Bench)によるコネクションプーリングの検証を行いたいと思います。
ご指摘有難うございます。


[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

phpを使用してOracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。MySQL編

まず始めに

文章が長くなってしまったので、MySQL編とOracle Database XE編に分けて記事にしたいと思います。

[追記]
コメント欄にてご指摘頂いた件がありますので、下記検証結果は今のところ正しいと言えないかもしれません。
僕がこのように検証しましたという程度で読んで頂けると幸いです。
再度違う方法で検証&報告します。


最近”コネクションプーリング”というのを知りました。

コネクションプーリングとは

データベースにアクセスする時、アクセスのたびに接続(コネクション)を確立するのではなく、あらかじめ一定数のコネクションを確立しておき、それを使い回す手法。データベースアクセスの負荷を減らすために用いられる。



引用元:コネクションプーリング 【connection pooling】 | ソフトウェア用語辞典
http://ew.hitachi-system.co.jp/w/E382B3E3838DE382AFE382B7E383A7E383B3E38397E383BCE383AAE383B3E382B0.html

色々php,mysql関連の本読みましたけど、コネクションプーリングについて触れている本ってあったかな?
コネクションプーリングをウェブで調べてみると賛否両論あるみたいですけども、実際のとこ動作させてみないとわからないもんで。

そこで、phpを使用して、Oracle Database XEとMySQLへのコネクションプーリングの方法・性能を比較しました。

処理性能を比較する方法

まず処理性能を比較する為のスクリプトは、下記の実行時間を表示する標準関数を使用します。

time.php
<?php
  $start = microtime();

  for($i=0;$i<10000;$i++){}

  $end = microtime();
  echo "\n".$end - $start;
?>

実行すると

php time.php
0.000884

こんな感じで実行時間が表示されます。
この実行時間で処理性能を比較したいと思います。

参考サイト
http://nakayalog.net/?p=235


まずphp + MySQLを使用してコネクションプーリングを利用する方法を調べました。

mysql_pconnect関数
http://jp2.php.net/manual/ja/function.mysql-pconnect.php

持続的データベース接続についての詳しい説明
http://jp2.php.net/manual/ja/features.persistent-connections.php

mysql_pconnect関数を使用すると、スクリプトの実行が終了してもMySQLとの接続が閉じられないということらしいです。
じゃあ、いつMySQLとの接続が切れるんだって話だけども…。

まあまあ早速実験開始です。


mysql_connect関数でINSERTクエリ1万回の速度実験

mysql_connectデータベースの作成

CREATE DATABASE `mysql_connect` ;

test_tableテーブルの作成

CREATE TABLE `mysql_connect`.`test_table` (
`test_field` INT NOT NULL ,
PRIMARY KEY ( `test_field` )
) ENGINE = InnoDB

mysql_connect.phpの作成

<?php
$link = mysql_connect('localhost', 'root', '[パスワード]');
mysql_select_db('mysql_connect', $link);

$result = mysql_query("INSERT INTO `mysql_connect`.`test_table` (
                       `test_field`
                       ) VALUES (
                       ".$argv[1]."
                       );");
mysql_close($link);
?>

mysql_connect.php用のtime.phpの作成

<?php
  $start = microtime();

  for($i=0;$i<10000;$i++){
    exec("php mysql_connect.php $i");
  }

  $end = microtime();
  echo "\n".$end - $start;
?>


それでは実行です。

php time.php
-0.16822

っておい!マイナスってなんだよ!過去行っちゃいましたよ。

なんでだろーと思って、time.phpを下記に修正してデバッグ

<?php
  $start = microtime();

  for($i=0;$i<10000;$i++){
    exec("php mysql_connect.php $i");
    echo microtime()."\n";//ここを追加しました。
  }

  $end = microtime();
  echo "\n".$end - $start;
?>

実行結果

0.13497400 1235517635
0.21877200 1235517635
0.30137900 1235517635
0.38148700 1235517635
0.46109300 1235517635
0.51826300 1235517635
0.57506100 1235517635
0.64548400 1235517635
0.72877100 1235517635
0.80903100 1235517635
0.89188100 1235517635
0.97485400 1235517635
0.12529500 1235517636
0.20909600 1235517636
0.29497800 1235517636
0.37752300 1235517636
0.46024800 1235517636
0.54040300 1235517636
0.60471400 1235517636
0.66184100 1235517636
0.71674400 1235517636
0.77201900 1235517636
0.82703400 1235517636
…

なるほど、[コンマ 秒]って事ですね。

では、それ用にtime.phpを下記の様に修正

mysql_connect.php用のtime.phpの作成(修正版)

<?php
  $start = array_sum(explode(" ",microtime()));

  for($i=0;$i<10000;$i++){
    exec("php mysql_connect.php $i");
  }

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>


それでは再度実行です。

php time.php
785.43530797958

かなり時間かかりましたね。
InnoDBというのも遅い原因かもしれません。


mysql_pconnect関数でINSERTクエリ1万回の速度実験

データベースとテーブルは先程のを使用します。

mysql_pconnect.phpの作成

<?php
$link = mysql_pconnect('localhost', 'root', '[パスワード]');
mysql_select_db('mysql_connect', $link);

$result = mysql_query("INSERT INTO `mysql_connect`.`test_table` (
                       `test_field`
                       ) VALUES (
                       ".$argv[1]."
                       );");
?>

mysql_close()を使用した行を削除しただけですが、きちんとコネクションプーリング出きるでしょうか?

mysql_pconnect.php用のtime.phpの作成

<?php
  $start = array_sum(explode(" ",microtime()));

  for($i=0;$i<10000;$i++){
    exec("php mysql_pconnect.php $i");
  }

  $end = array_sum(explode(" ",microtime()));
  echo "\n".$end - $start;
?>

それでは実行です。

php time.php
775.68468093872

10秒短くなったけど…少し違う感じがするなあ。


MySQLコネクションプーリングの結果

一応速度の向上を測る事が出来ましたが、微々たる速度向上という結果でした。


php + MySQLでの結果は良い結果は出ませんでしたが、改善方法をお知りの方は教えて下さい!

次のエントリーではphp + Oracle Database XEのコネクションプーリングを検証したいと思います!

[追記]
id:sh2さんからご指摘頂きました!
同じような検証をされたようです。
http://d.hatena.ne.jp/sh2/20081104/



[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/

MySQLからOracle Database XEへマイグレーションする事が出来るツールOracle SQL Developerを使用してみました。

先月の記事の中では、MySQLOracle Database XEの使用メモリ数や、プロセスの動作を比較したのですが、MySQLのデータベースやテーブル、データ等をOracle Database XE上で動作させたいなー、となると、データベース設計をし直す等、余計な作業が発生する必要があるのでは無いかと思っていたのですが、MySQLからOracle Database XEへ簡単に移行が出来るツールがありました!

oracleのサイトにありますOracle SQL Developerというツールを使うと簡単にマイグレーション作業をする事ができます。

Oracle SQL Developerのインストール

Oracle SQL Developerは下記URLからダウンロード出来ます。
http://www.oracle.com/technology/global/jp/software/products/sql/sql121/sql121_dl.html


ダウンロードして、Oracle SQL Developerを起動すると、いきなりjavaのパスを入力して下さいと言われたので、JDKをインストールしました。

下記URLからダウンロード
http://download.java.net/jdk6/6u3/promoted/b05/index.html

Windows Offline Installation, Multi-language JDK fileをクリックしてJDKをダウンロードしました。

javaのパスを入力すると下記の画面が表示されました。
(ちなみに僕の環境(Windows XP)だとC:\Program Files\Java\jdk1.6.0_03\bin\java.exeになります。)

これでOracle SQL Developerのインストールが出来ました。

Oracle SQL Developerを使用して、MySQLOracle Database XEへ接続

インストールしただけでは、MySQLへアクセスする事が出来ないので、Tools > Preferences 画面の、
Database > Third Party JDBC Drivers 画面からJDBC Driverを追加します。

MySQL用のJDBC Driverは下記のサイトからダウンロード出来ます。
http://dev.mysql.com/downloads/connector/j/5.1.html

Add Entryボタンを押して、下記のファイルを指定しました。
C:/Program Files/sqldeveloper/mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar

これでMySQLに接続出来るようになりました。


Oracle SQL Developerを使用して、実際にMySQLに接続してみたいと思います。
左上のタブのFile > Newボタンを押して、データベースコネクションを作成します。
画面のOKを押すと下記の画面が表示されました。

MySQLタブをクリックして、入力欄にMySQLへのアクセス情報を入力してTESTボタンを押したところ、

上記のエラーが表示されました。

192.168.11.9(クライアントPC)からは接続出来ないというエラーのようです。

検索すると、下記のページを参考にすると解決できました。
http://dev.mysql.com/doc/refman/4.1/ja/access-denied.html

userテーブルに192.168.11.9を許可するようにデータを追加して、コマンドで mysqladmin flush-privileges -u root -p[パスワード]を実行すると解決し、無事接続できることを確認できました。

localhost以外からMySQLに接続する設定の方法を始めて知りました!

その後、上記のMySQLのデータベースコネクション追加の方法と同じように、oracleのデータベースコネクションを追加しました。(この作業はすんなり出来ました。)

これで、マイグレーションの準備が完了です。

実際にマイグレーションを実行

マイグレーションを実行するには、Migration > Quick Migrationの画面を開きます。

Verifyのボタンを押してマイグレーションが実行出来るかテストした後、Migrateボタンを押すことでマイグレーションを実行する事が出来ます。

おおお!超簡単!

まとめ

JDBC Driverのダウンロード&インストールや、接続するMySQLの設定の変更等でつまずいてしまうところもあったのですが、接続情報を設定するだけで、簡単にマイグレーション作業が出来てしまってびっくりしました。



[PR]Spreeの情報を集めています。

ECを持ちたい方、仕事でECを使いたい方向けのコミュニティサイトです。
このサイトでは世界で最も使用されているECの1つであるSpreeについての情報を提供しています。
http://spreecommerce.jp/