いろいろ準備中

[mysql][Apache] mod_log_sql関連のベンチマーク

12月 2nd, 2008 Posted in apache, MySQL

前回設定した項目についてベンチマークをとりました。

今回のテストケースは

  1. 通常のaccess_log(ファイル)に保存
  2. BufferedLogsディレクティブをONにしたaccess_log
  3. mod_log_sql+MyISAMストレージエンジン
  4. mod_log_sql+Archiveストレージエンジン

の4つです。

それぞれ上記設定をしたwebサーバに、apacheのabコマンドを使ってテストしました。

# /usr2/apache2/bin/ab -c 100 -n 10000 http://example.com/

1度に100ユーザ同時接続し、合計で10000回リクエストをかけています。

リクエストをかけると、以下のようなシンプルなレスポンスが帰ってきます。
これは静的ファイルで用意されています。

<html>
<body>
test
</body>
</html>

まずは1秒間あたりのリクエスト処理数です。

■1秒間あたりのリクエスト処理数

テストケース リクエスト数/秒 1に対する割合
1 7598.81 100%
2 8670.88 114.1%
3 4340.90 56.7%
4 3119.29 41.0%

mod_log_sqlを使うと、MyISAMを用いた場合はもともとの57%弱、Archiveに至っては40%程度しかパフォーマンスが出ていません。結構性能が落ちていますね。

INSERTパフォーマンスは、ArchiveだとMyISAMの1.5倍くらいあると聞いていたので、Archiveのほうがパフォーマンスがよくなると予測していたのですが、そのような結果にはなりませんでした。同時接続数とか条件で変わってくるのかもしれませんが、今回は検討しません。

続いて、ログファイルのサイズについて検討します。

dbに保存されたデータについては、

SHOW TABLE STATUS LILE 'access_log'\G
*************************** 1. row ***************************
                Name: access_log
              Engine: ARCHIVE
             Version: 10
      Row_format: Compressed
               Rows: 119070
 Avg_row_length: 11072
      Data_length: 2764858
Max_data_length: 1318343040
     Index_length: 0
         Data_free: 0
 Auto_increment: NULL
      Create_time: 2008-12-02 16:30:49
     Update_time: 2008-12-02 16:30:49
      Check_time: NULL
          Collation: utf8_general_ci
         Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

のData_lengthフィールドで確認します。Row_formatフィールドからArchiveではデータが圧縮されて保存されることもわかります。

10000回リクエストをかけた後のログのサイズは以下のとおりです。

■10000リクエスト後のログのサイズ

テストケース Kbyte 1に対する割合
1 646 100%
2 658 101.9%
3 1100 170.3%
4 256 39.6%

なんと、Archiveではもともとのaccess_logの40%程度のサイズに圧縮されています。本領発揮というところでしょうか。

逆に、MyISAMでは70%もサイズが増えてしまいました。これはちょっと実運用では厳しい感じがします。

ただし、まだ試していませんが、myisampackというものでデータを圧縮することができます。
定期的にテーブルの圧縮をすることでログのサイズが抑えることができそうです(テーブルの変更が不可となりますが)。また、読み込みも早くなるということなので、時間があれば試してみたいです。

最後に、保存したログについてMyISAMとArchiveについてSELECTのパフォーマンスを調べました。

テスト条件は以下のとおりです。

データはこんな感じです。

mysql> desc access_log;
+------------------+----------------------+------+-----+---------+-------+
| Field            | Type                 | Null | Key | Default | Extra |
+------------------+----------------------+------+-----+---------+-------+
| id               | char(19)             | YES  |     | NULL    |       |
| agent            | varchar(255)         | YES  |     | NULL    |       |
| bytes_sent       | int(10) unsigned     | YES  |     | NULL    |       |
| child_pid        | smallint(5) unsigned | YES  |     | NULL    |       |
| cookie           | varchar(255)         | YES  |     | NULL    |       |
| machine_id       | varchar(25)          | YES  |     | NULL    |       |
| request_file     | varchar(255)         | YES  |     | NULL    |       |
| referer          | varchar(255)         | YES  |     | NULL    |       |
| remote_host      | varchar(50)          | YES  |     | NULL    |       |
| remote_logname   | varchar(50)          | YES  |     | NULL    |       |
| remote_user      | varchar(50)          | YES  |     | NULL    |       |
| request_duration | smallint(5) unsigned | YES  |     | NULL    |       |
| request_line     | varchar(255)         | YES  |     | NULL    |       |
| request_method   | varchar(10)          | YES  |     | NULL    |       |
| request_protocol | varchar(10)          | YES  |     | NULL    |       |
| request_time     | char(28)             | YES  |     | NULL    |       |
| request_uri      | varchar(255)         | YES  |     | NULL    |       |
| request_args     | varchar(255)         | YES  |     | NULL    |       |
| server_port      | smallint(5) unsigned | YES  |     | NULL    |       |
| ssl_cipher       | varchar(25)          | YES  |     | NULL    |       |
| ssl_keysize      | smallint(5) unsigned | YES  |     | NULL    |       |
| ssl_maxkeysize   | smallint(5) unsigned | YES  |     | NULL    |       |
| status           | smallint(5) unsigned | YES  |     | NULL    |       |
| time_stamp       | int(10) unsigned     | YES  |     | NULL    |       |
| virtual_host     | varchar(255)         | YES  |     | NULL    |       |
| bytes_in         | int(10) unsigned     | YES  |     | NULL    |       |
| bytes_out        | int(10) unsigned     | YES  |     | NULL    |       |
+------------------+----------------------+------+-----+---------+-------+
27 rows in set (0.00 sec)
 
mysql> select COUNT(*) access_log;
+------------+
| access_log |
+------------+
|        10060 |
+------------+
1 row in set (0.00 sec)

テーブルの読み込む条件は以下のとおりです。

mysql> select * from access_log;
mysql> select count(*) from access_log where time_stamp >=1227852970 AND time_stamp < 1227853300;

結果は以下のようになりました

■DB読み込みのテスト(where条件なし)

MyISAMに対する割合
MyISAM 0.72 100%
Archive 4.12 580.3%

■DB読み込みのテスト(where条件あり) ※ヒット件数は71472件

MyISAMに対する割合
MyISAM 0.59 100%
Archive 3.87 655.9%

MyISAMのほうがぜんぜん早いですね。Archiveのほうはデータが圧縮されているので、その分読み込みに時間がかかっているのかもしれません。

読み込みに結構な差が出ていますが、これに関してはログを収集するサーバをマスタ-スレーブ構成にして、スレーブのほうでSELECTをかけるような処理を行えば対処できそうなきがします。

■まとめ

今回の結果では、結局テストケースとして用いたものについてはどれも一長一短で、それぞれの目的や用途に合わせる必要があるという事になりました。

無難に行くなら通常のaccess_logを用いて、どうしてもパフォーマンスをあげたい場合は、現在β版という位置づけではありますがBufferedLogsディレクティブをONにする方法が考えられます。

逆に、パフォーマンスはそれほど問題にならなくて、ログの管理のしやすさやサイズが重要な項目になるならば、迷わずmod_log_sql+Archiveストレージエンジンという組み合わせがよいですね。

コメントを投稿する