とあるリーマン日記

ガジェット、艦これアーケード、アフェリエイト、アニメ、声優、アフェリエイト関係が話題に中心になると思います。よろしくお願いいたします。

postgresqlが遅い。

なんか最近疲れてる。

仕事でapache+tomcat+postgresql+java構成のとあるwebアプリケーションのサーバ構築・管理、アプリケーションのプログラム改修をやってるんです。

立ち上げ当初は、接続数が多くなるとtomcatが動かなくなる不都合がありました。tomcat自体、JVM上で動いているのでJVMに割り当てられているメモリ内で動くんです。
単純にユーザー1人当たり10Mメモリを消費したとして、100人接続するためには1Gのメモリをtomcatに割り当てなければいけません。
メモリ余ってるんだから、思い切って割り当てれば?と思うかもしれませんが、話はそんな簡単じゃない。
JAVAのメモリ管理が複雑で、ご存知の通りメモリ解放をガーベージコレクション(世代別)で行ってます。旧世代領域にオブジェクトが沢山貯まるタイプのアプリケーションだと、かなり苦労させられます。フルGCが発生しない限り旧世代領域は掃除されませんから、メモリにオブジェクトが貯まっていく一方なのです。
そして、一旦フルGCが発生すると、それが終了するまでWEBアプリケーションのスループットが極端に落ちてしまうという・・・。
いわゆるstop the worldという奴です。良く@ITの記事で見かけます。

沢山のメモリを1つのtomcatに割り当てるということはフルGCがかかるタイミングを遅らせることはできるけれど、その分だけフルGCに掛かる時間が増えてしまい、かえって逆効果な訳です。
じゃ、今はどうしてるかというと・・・。
tomcatを数本立ち上げて(今は4本立ててる)、負荷分散を行ってます。

で、安心してまったりとしていたら、今度はpostgresqlが遅いという問題が発生。(正確にいうとpostgresには問題は無いんだ・・・)
データベースへ同時に多数のアクセスがあったら、ずっとpostgresがCPUを100%使い続けるという・・・。
時間かかってもいいからトランザクションを完了してくれればいいのだけれどね。トランザクションを処理しきれない状態になってる。

まあ、原因はおよその見当はついていた。
くさってもOracleマスターでデータベース屋ですから。

postgresqlのログを見たら、どうやらSELECT実行にやたらと時間が掛かってる模様。(だいたい6000msecくらい)

やれることとしては、3通りあります。
postgresqlの設定値を見直してチューニングする。
ボトルネックとなっているロジック(プログラム)を直す
・表の構造を工夫する(マテリアルライズドビューを作成するとか、正規化した表同士を逆にくっつけるとか、インデックスたんを付けるとか))

とりあえずソース見てみたら、INNER JOINが入れ子で何層にもなっているSELECT文を発見したので、プログラムを直す方向性で現在は動いています。(SELECTで遅くなる原因の多くはインラインビュー(FROMの中でSELECT書いてる奴)のなかで集約関数を使ってるケースだから。)
どのように修正してるかというと、大雑把には、SELECT自体はもの凄く単純にして、合計とか最大とか最小とかの集計処理(DBMSに負荷がかかるような処理)は、全部プログラム側で処理するようにしただけなんだ。
まだテスト段階ですが、おかげさまで6000msec掛かっていた処理が4msec程度で終わるようになってます。^^;

まあ、そんなことを毎日やってます。

それよりも、はやくSC2やりたいのだけれど・・・。
変な日記かいてしまったじゃねーヵ。