Apache、Tomcatのチューニング
チューニング方法はメモリとインデックスしかない
・メモリ 32bit,64bit
64bitだとメモリの消費量が高いとされて実際高い
・PAE
32bitで4GiB以上のメモリを使う技術
Apache チューニング
1.HostnameLookups -> off
これがonだと、ログファイルにホスト名を出力するためDNSLookupしてしまう
2.無駄なログファイルを消す
ローテートする
3.無駄なモジュールをロードしない
4..htaccessを無効にする
※アクセスのたびにソンァイチェックをおこなうのでパフォーマンスが劣化する
※AllowOverride -> None
5.KeepAlive -> off
※HTTPはステートフルな接続のためリクエストのたびに接続切断が発生するためコストがかかる
※LBに格納されている場合あまり意味がない
6.MNM(Multi Proccessing Module)の選定
※preforkとworker
prefork 1リクエスト 1プロセス
-> mod_phpなどを使う場合はprework
worker 1リクエスト 1スレッド
-> マルチプロセス + マルチスレッド ハイブリッドモデル
-> プロセス数 * スレッド数 = Max Client
-> 1つのプロセスを立ち上げるよりも1つのスレッドを立ち上げる方が負荷が低い
7.無駄にプロセス起動、プロセスkillさせない
※以下の値を均等に保つ
※MaxRequestsPerChild 4000 を超えてもその対象のプロセスのみが終了->起動するだけ
StartServers 60
MinSpareServers 60
MaxSpareServers 60
MaxClients 60
※MPMがworkerの場合
ThreadsPerChild 25 × スレッド数 = MaxClients
ab
単純なストレスツール
#ab -n 1000 -c 100 http://192.168.0.50/ <=最後の/は必須
Requests per second: 4270.68 [#/sec] (mean) <=1秒あたりのリクエスト回数
※スループットがこれ
tomcat
1.connectorの選択
※AJPかHTTP 汎用性の高いHTTPを使った方が無難
2.スレッドのパラメータ
maxThreads
minSpareTHreads
connentonTimeout
※基本はデフォルトで
3.不要なログを出さない
4.enableLookups -> off
vm
GCの利点
1.メモリリークを防ぐ
2.ダブルフリーを防ぐ
3.無効なポインタ参照を防ぐ
GCの欠点
1.FullGCの発生時にすべてのスレッドが停止する
2.GCが消費したメモリ量に対応して発生するため制御しづらい
JConsole
※JMX(java management Extensions)を有効に
s0,s1がいっぱいだとEdenから直接OLDにいく
これだとFullGCでしか消せない
全体領域だけでなくNEWフィールドも増やす
起動パラメータに追加
CATALINA_OPTS="${CATALINA_OPTS}
- Dcom.sun.management.jmxremote=true
- Dcom.sun.management.jmxremote.port=3337
- Dcom.sun.management.jmxremote.authenticate=false
- Dcom.sun.management.jmxremote.ssl=false"
負荷分散
分散問い合わせの種類
1.ラウンドロビン
ただ単に順番に見に行っているだけ
単純な振り分けなのでCPUを使わないが、すべてのSlaveに完全なデータセットが必要
2.重み付けラウンドロビン
単純な振り分けだが、ハードウェアの性能に差がある場合などに有効。
これもすべてのSlaveに完全なデータセットが必要になる。
3.接続数最小
振り分け対象のサーバの中で一番現在の接続数が最小のものを選択してリクエストする。
リソース消費が少ないと思われるサーバを使用できるが、これもSlaveで完全なデータセットが必要であり、AP側でDBの接続数を聞きにいかなければいけない。
4.応答時間最短
定期的に各サーバへの応答時間をテスト用のリクエストで計測してその時間が最小のサーバに寄せていく振り方。
実際に計測した時間で重み付けされるので、性能の違うサーバが並んでいてもレスポンスが標準化される。
直近のテスト結果をストアしておく必要がある。
5.AP-DBサーバ固定
対応するAPサーバが処理するときに必要なデータのサブセットのみがDBサーバにあればいい。
対応するAPサーバ以外は対応するDBサーバを利用できないため、上位での分け方を行わないとリソース消費に偏りが出る。
6.リスト
問い合わせ対象のデータによってリストからw欄だサーバに問い合わせする振り方。
DBサーバはリストに対応するデータのサブセットだけもってればいい。
設計時になるべく一様になるキーを選ばないとリソースに偏りが出る。
7.レンジ
問い合わせ対象のデータによってレンジを求め、そのレンジに対応するサーバに問い合わせする振り方。
8.ハッシュ
問い合わせ対象からハッシュを求め、そのハッシュ値で選んだサーバに問い合わせする振り方。
DBサーバはハッシュに対応するデータのサブセットだけを持てばいい。
データのサブセットのみを持つと更新側にも同じルールの適用が必要。
分散KVS
NoSQL
格納データは単純さを求めた結果、PKと値という単純なデータ構造になってきた。
NoSQLの定義
1.キーと値
2.問い合わせにSQLのような重い解析を必要とする問い合わせ言語を必要としない
3.データは分散して配置され冗長性が高い
4.高負荷でもスループットが高い
相性がいいサービス
1.参照更新頻度が高い
2.データの更新参照に一時的に一貫性がなくてもいい
3.増え続ける大量のデータを格納したい
4.非正規化が容易
レプリケーションを利用した負荷分散
■スキーマ別レプリケーション
スキーマ別やテーブル別で分散する事ができる。
「Replicate_Do_DB」
my.cnf設定例
replicate-do-db = database1
replicate-do-db = database2
replicate-do-db = database1,database2
■テーブルごとの分散
「Replicate_Do_Table」
テーブルごとにSlaveサーバを分散する構成
※テーブルごとのレプリケーションとJOINは切っても切り離せない
物理的にJOINできない
my.cnf設定例
replicate-do-table=db_name.table_name
■ユーザーのIDをキーにしてテーブルの分割
ユーザーのIDを
キーにしてテーブルの分割を行い
レプリケーションで分散する
水平分割
■ストレージエンジンとレプリケーション
ストレージエンジンとレプリケーションを使った負荷軽減
MyISAMはトランザクションを使えない。
参照だけMyISAMを使う構成。
InnoDBも高速になってきたので、これはだんだんなくなった。
SELECTの発行回数が多い場合はSlaveサーバのストレージエンジンをMemoryエンジンにすることで速くなる。
alter table テーブル名 engine=memory;
■Masterサーバには不要なデータあるとき
MasterサーバのストレージエンジンをBLACKHOLEエンジンにすることで
MasterサーバのI/O負荷を軽減することが出来ます
BLACKHOLEエンジンはデータを保存・更新しないストレージエンジンになります
バイナリファイルのみ出力するので、Slaveに対してはデータが更新される。
http://blog.goo.ne.jp/sohgoh/e/44b19464bec097cb8063e42736639bcd
■Jdbcでのロード・バランシング
jdbc:mysql:loadbalance://host-1,host-2,...host-n/database?loadBalanceBlacklistTimeout=5000
jdbc:mysql:loadbalance://192.168.0.50:3306,192.168.0.50:3306/ensyu1
jdbc:mysql:loadbalance://192.168.0.50:3306,192.168.0.50:3306/ensyu1?loadBalanceBlacklistTimeout=5000
■はまりどころ
SLAVE START;
以降にreplicationされるのですが
これ以降のmasterへのupdateしか反映されません。
ですので、slave-master間の同一性を保つためには
replicationを開始する前に双方のデータベースの内容を同一にしておかなければなりません。
実行計画とレプリケーション
実行計画 EXPLAIN
クエリとスキーマの最適化を見極める。
http://dev.mysql.com/doc/refman/5.1/ja/explain.html
※show slave status \G でテーブルがみやすくなる
mysql> explain select * from emp;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | SIMPLE | emp | ALL | NULL | NULL | NULL | NULL | 50346 |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 row in set (0.10 sec)
1.id
SELECT識別子。クエリ内におけるこの SELECTの順序番号
2.select_type
だいたいこれ-> SIMPLE 単純なSELECT (UNIONやサブクエリを使用しない)。
simple
primary
union
union result
※↑これら意外がでたら疑う。
unionクエリの場合これになる↓
mysql> explain select * from emp union select * from emp;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | PRIMARY | emp | ALL | NULL | NULL | NULL | NULL | 50346 | |
2 | UNION | emp | ALL | NULL | NULL | NULL | NULL | 50346 | |
NULL | UNION RESULT | |
ALL | NULL | NULL | NULL | NULL | NULL |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
3 rows in set (0.00 sec)
3.table
結果を得るために参照するテーブル。
4.type
各結合型を最適なものから順に紹介する。
1.「const」 OK PK、UNIQUEインデックスでの等価検索
2.「ref」 OK UNIQUEじゃないインデックスを使用検索時
3.「range」 微妙 インデックスを使用した範囲検索時
4.「index」 微妙 index内でのフルスキャン
5.「ALL」 アウト 全表操作している。
■constになる場合
mysql> explain select * from emp where empid = '1';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | SIMPLE | emp | const | PRIMARY | PRIMARY | 4 | const | 1 |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 row in set (0.00 sec)
テーブルに、一致するレコードが最大で 1 つあり、クエリの開始時に読み取られる。レコードが 1 つしかないため、このレコードのカラムの値はオプティマイザによって定数と見なされる。constテーブルは、1 回しか読み取られないため、非常に高速である。
この場合、typeはconstになる
■rangeになる場合
インデックスを使用して、一定の範囲にあるレコードのみが取り出される。
mysql> explain select * from emp where empid > '1';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | SIMPLE | emp | range | PRIMARY,test_idx | PRIMARY | 4 | NULL | 25294 | Using where |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 row in set (0.01 sec)
■refになる場合
mysql> explain select deptid, count(*) from emp where hiredate = '1900/04/01';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 | SIMPLE | emp | ref | test_idx | test_idx | 4 | const | 2423 | Using where; Using index |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1 row in set (0.00 sec)
ユニークじゃないインデックスで検索時
■ALLになる場合
インデックスを削除した。
フルテーブルスキャンが実行される。
不適切。
■※注意関数を使うとインデックスを使わない
mysql> explain select deptid, count(*) from emp where cast(hiredate as date) = '1900/04/01' group by deptid;