MySQL と PostgreSQL のベンチマーク第3弾。Webアプリでのパフォーマンス比較。
アプリケーションは mod_perl で実装した、
という動作をするもの。検索には全てインデックスが使用されるように設定。
ab (apache bench) で、多重度を 1 5 10 25 50 として 100秒間測定、というシェルスクリプトでベンチマークしてみる。 環境は OS=Kondara-2.1RC1, Apache 1.3.22, mod_perl 1.26, Apache::DBI 0.88, CPU=Duron 800MHz, Mem=384MB。
結果。数字は Requests/sec.
DB/多重度 1 5 10 25 50 --------------------------------------------------------------------------- MySQL(InnoDB) 86.02 85.15 84.62 78.41 68.23 MySQL(InnoDB) + Apache::DBI 98.06 98.37 98.68 96.32 81.93 MySQL(MyISAM) + Apache::DBI 102.28 103.07 102.69 98.95 82.95 PostgreSQL 26.33 27.25 27.40 28.03 23.40 PostgreSQL + Apache::DBI 73.59 72.73 74.53 72.28 69.02
MySQLは、更新の必要なユーザ情報テーブルを InnoDB にした場合と、MyISAM にした場合それぞれ測定 (ログ記録、郵便番号テーブルはどちらも MyISAM)。
MySQL は Apache::DBI を使わない場合でもかなりパフォーマンスが高い (=接続のコストが安い)。 PostgreSQL は Apache::DBI を使うと3倍近くパフォーマンスが向上する。
しかし、上記の結果、MySQL と PostgreSQL の差が (Apache::DBIを使うと) あまりでてないような。もしかしてこれ、Webアプリの方が CPU を食っていて、そっちがボトルネックになっているのではないか?
...
Celeron1.2G, 256MB RAM のマシン (Kondara-2.1RC1) を Webサーバとして投入。 DBは上と同じ、Duron 800, 384MB RAM のマシンでベンチマークを取り直す。 2台のマシン間は 100Base-T で接続。(スイッチングハブ使用)
WebサーバをDBサーバと別にした場合の結果。(Apache::DBI 使用。MySQL は MyISAM)
1 5 10 25 50 MySQL 143.46 164.31 168.25 163.53 158.67 PostgreSQL 96.15 132.37 138.17 137.75 139.47
ベンチマーク中、WebサーバのCPU使用率はほぼ 100%。DBサーバは、 MySQL の場合で 30% 前後。PostgreSQL だと 60-70% 程度。 つまりこれ、Webサーバのほうで律速になってたわけね・・・だめじゃん。
意地になったので Webサーバをもう1台投入することに。 Celeron 800, 256MB RAM のマシン (Kondara-2.1 β3)。よもや自宅で3台マシンを並べてベンチを走らせることになろうとは。
Webサーバ1台構成の時と同様の条件で、2台のWebサーバに同時に ab でリクエストを投げてみる。 下記は2台分の数値を合計した値。
1 5 10 25 50 MySQL 268.77 251.27 289.38 279.36 277.21 PostgreSQL 160.79 158.77 184.52 175.82 183.88
これでようやく(?) MySQL と PostgreSQL に大差が。 MySQL は、1台構成のときよりも 1.7倍程度向上。 追加した2台目の方がCPUが遅いことを考えると、ほぼリニアに処理能力が上がっているとみてよい。 PostgreSQL は 1.3倍程度の向上にとどまっている。 ベンチマーク中の CPU 使用率は、MySQL だと 60-70%程度、PostgreSQL はほぼ100%。 MySQL ならば、もう1台 Web サーバを追加してもパフォーマンス向上が見込めるが、PostgreSQL ではおそらくほとんど向上しないはず。
こうなったら MySQL が悲鳴を上げるまで、Celeron466 のマシンやら C3 667 のやら、Libretto L1 やらを追加してやろうか・・・ と思わないでもなかったのだが、ベンチマークを1セット (上の結果での1行分) 実行するのに実時間で40分ほど掛かる。さすがにそればっかりやって週末を潰すのもなあ、ということで見送り。
...
追記。DBサーバ側の最大同時接続数を256まで増やした。その方法。
MySQL の場合、/etc/my.cnf に
set-variable = max_connections = 255
を追加。
PostgreSQL の場合、/var/lib/pgsql/data/postgresql.conf に
max_connections = 256 shared_buffers = 512
を追加。
PostgreSQL でのベンチ実行時に、
[Sun Feb 24 05:54:31 2002] [error] DBI->connect(dbname=bench;host=192.168.0.3) failed: FATAL 1: cann ot open /var/lib/pgsql/data/PG_VERSION: Too many open files in system
というようなメッセージが。'Too many open files in system' てことは、ファイルディスクリプタが足りてない。 DBサーバマシン上で、
# echo 65536 > /proc/sys/fs/file-max
として、ファイルディスクリプタを増やす。