よく聞く話ですが、多分あんまり効果ないです。
テストテーブルはこんな。
CREATE TABLE t1 (num serial,val char(32) not null);
numには1~1,000,000の整数値が、valにはMD5(num)の値が入ってます。
投げるクエリはこんな。
SELECT sql_no_cache * FROM t1 ORDER BY val LIMIT 1;
INDEXを全然使わない`重い'クエリ。転送量がネックになってほしくないのでLIMIT 1。
mysqlクライアントから直接叩いても2秒ちょいかかる。
これをPerlにしてapache越しに呼ぶ様にする。
MySQLのmax_connectionsを10に設定して、いざ測定。
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
abをバックグラウンドで2つ動かしてやって、10コネクション * 2回繰り返し * 2クライアントから、とする。
...
Time taken for tests: 33.176 seconds
Complete requests: 20
Failed requests: 1
...
Time taken for tests: 38.575 seconds
Complete requests: 20
Failed requests: 11
$ tail -f /var/log/httpd/error_log
...
[Tue Jun 12 23:15:38 2012] [error] [client ::1] DBI connect('d1','root',...) failed: Too many connections at /var/www/cgi-bin/test.cgi line 12
[Tue Jun 12 23:15:38 2012] [error] [client ::1] Can't call method "prepare" on an undefined value at /var/www/cgi-bin/test.cgi line 13.
...
都合12回Too many connectionsで失敗したのかな。
合計40のリクエストなんで、30%の失敗。
対比としてテーブルにINDEXをつけて`軽い'クエリに仕立て上げる。
ALTER TABLE t1 ADD INDEX (val);
mysqlクライアントから直接叩くと0.00秒で結果が返ってくる様になった。
これ以外は何も変えない。
apacheを再起動してから同じabを試す。
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
...
Time taken for tests: 8.606 seconds
Complete requests: 20
Failed requests: 0
...
Time taken for tests: 8.765 seconds
Complete requests: 20
Failed requests: 0
...
error_logにも何も出ない。
スクリプトもデータもパラメータもいじらず、ALTER TABLEだけで事情が解決することもあるってことで。
ちなみに、INDEX作る前の状態で、max_connections = 100にして測定しようとしたら、
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
$ ab -n 20 -c 10 http://localhost/cgi-bin/test.cgi &
...
Benchmarking localhost (be patient)...apr_poll: The timeout specified has expired (70007)
Benchmarking localhost (be patient)...apr_poll: The timeout specified has expired (70007)
abがタイムアウトして結果すら出なくなった。
タイムアウト値いくつか知らないけど、予想通り性能は劣化するよね。。
0 件のコメント :
コメントを投稿