前回のおさらい

前回は性能テストの時間のリスナーログを確認したところ、サイズが尋常でないことが発覚したところで終わりました。
たろーちゃんの伝家の宝刀『血液検査』の出番です

再度、外部のアプリケーション開発会社に確認

たろーちゃんは再び、アプリケーションの開発元に問い合わせることにしました。

開発者「はい、なんでしょうか?」
たろー「御社で開発されているアプリケーションですが、『 コネクションプーリング 』は使用されていますか?」
開発者「?!・・・なんですか?」
たろー「『 コネクションプーリング 』です。」
開発者「??」
たろー「…えーっと、SQLを発行するとき、毎回データベースとの接続&切断を繰り返す仕組みでプログラミングされていますか?」
開発者「そうなってますけど・・・」
たろー「わかりました、おそらくそれが原因です。SQL自体は 0.01 秒と早いのですが、コネクションの確立に毎回オーバーヘッドが掛かっているんです。SQLの実行回数も凄いので、 コネクションプーリング するようにして下さい。」

開発者

コネクションプーリング

みなさんはTCPというネットワークプロトコルを御存知でしょうか?
ネットワーク上でパケットをやり取りする際、TCPでは『3ウェイ・ハンドシェイク』と呼ばれる仕様でVC(ヴァーチャル・サーキット=仮想回線)を確立します。
VC確立後は、そのVCを使ってパケットのやり取りを行います。
Oracle Database のデフォルトのTCPポート番号は 1521 です。
1521と聞くと、馴染みのあるDBAの方も多いのではないでしょうか。
VC確立後、更にOracle*Net のレイヤーで専用サーバプロセスが fork(生成)され、そしてユーザパスワードの認証チェックや権限のチェックが行われます。

TCPコネクションの確立
専用サーバプロセスのfork(生成)
メモリ(UGA)の確保
Oracle Databaseによるユーザ認証、及び権限のチェック
SQLの実行
メモリ(UGA)の解放
専用サーバプロセスの消滅
TCPコネクションの閉塞

今回のシステムでは、これら一連の処理が、1つのSQLを発行する度に実行されているのです。
これらは発行されるSQLが多ければ多いほど、無視できないオーバーヘッドとなり、その負荷はダイレクトにCPUを直撃します。
これを防ぐため、『 コネクションプーリング 』という仕組みが存在します。
接続&切断を繰り返すのではなく、あらかじめコネクションを確立して、そのコネクションを使い回すのです。


コネクションプーリング を用いていれば、最初の1回だけ接続要求がある筈です。
リスナーログには大量の接続要求があり、また、 V$ACTIVE_SESSION_HISTORY を調べると、毎回 SESSION_IDとSESSION_SERIAL#が変わっていました。
このことから、たろーちゃんは コネクションプーリング が使われていないと気が付いたのです。
これなら『OSリソース状況では CPU を多く消費しているのに対し、 AWR レポート上ではそれ程 CPU を消費していない』という矛盾も、説明がつきます。
しかし・・・。

開発者

開発者「でもそれは、うちのアプリケーションの仕様です。」
たろー「え?」
開発者「お客様からは、『 コネクションプーリング を使え』との要件はありませんでした。」
たろー「いや、これは非機能要件ですし、第一それでは性能が・・・。」
開発者「うちのアプリケーションを修正することは出来ません。データベース側で対処をして下さい。」
たろー「待って下さい。アプリケーション側の協力がなくては、パフォーマンスチューニングはできません。」
開発者「そもそも『 コネクションプーリング 』なんて聞いたこともありません。そんなやり方は一般的ではないと思います。我々のアプリケーションに対して、とやかく言うのは辞めて下さい。
たろー「……。」


そう言うと、また一方的に電話を切られてしまいました。

たろー「データベース側で対処しろと言ったって・・・(怒)」


たろーちゃんは、またカチンときました。

オーバーヘッドを軽減するには?

ここで、オーバーヘッドについて、もう一度振り返ってみます。

TCPコネクションの確立
専用サーバプロセスのfork(生成)
メモリ(UGA)の確保
Oracle Databaseによるユーザ認証、及び権限のチェック
SQLの実行
メモリ(UGA)の解放
専用サーバプロセスの消滅
TCPコネクションの閉塞

アプリケーションに手を入れることが出来ない以上、この中でデータベース側で軽減出来ることは、

TCPコネクションの確立
専用サーバプロセスのfork(生成)
メモリ(UGA)の確保
Oracle Databaseによるユーザ認証、及び権限のチェック
SQLの実行
メモリ(UGA)の解放
専用サーバプロセスの消滅
TCPコネクションの閉塞
上記4つになります。

但し、『SQLの実行』は、今回は INDEX UNIQUE SCAN で十分早かったため、これ以上、早くすることは出来ないと判断しました。
オーバーヘッドを削減するため、たろーちゃんは、専用サーバ接続を諦め、共有サーバ接続を使うことにしました。

専用サーバ接続と共有サーバ接続

専用サーバ接続は、接続の度にプロセスをfork(生成)し、切断の度に消滅します。
共有サーバ接続は、あらかじめプロセスを fork(生成)しておき、切断されても消滅せずにクライアントの処理をその名のとおり『共有』して受け付けます。
『共有』なので、メモリ(UGA)領域も解放せず、そのまま使い回します。
そのため、専用サーバに比べて接続&切断に掛かるオーバーヘッドが少なくなります。

但し専用サーバ接続と共有サーバ接続を比べたとき、単純な性能では専用サーバ接続のほうが優れています。しかしながら今回のようなケースでは、SQL自体の負荷が軽いため、専用サーバプロセスと共有サーバプロセスの性能差が出にくいのです

それよりも、接続&切断に掛かるオーバーヘッドを削減することで、トータルな処理時間では共有サーバ接続のほうが専用サーバ接続より優ることがあります。
特に CPU やメモリの高負荷時に

★車で例えると、専用サーバプロセスはハイパワーターボ車で、共有サーバプロセスはテンロクのNA車です。長い下り坂でタイトなコーナー(オーバーヘッド)が連続して続く場合、ハイパワーターボ車はその力を限界まで引き出せる時間はごく僅かです。一方、テンロクのNA車はパワーこそ劣るものの、その軽量さゆえ、タイトなコーナーをスイスイとクリアしていくことができます。

あと内部的な話になりますが、専用サーバプロセスはUGAをPGA内に取ります。
一方、共有サーバプロセスはUGAを SGA の共有プール内に取ります。
これだと共有プールの負荷が高くなるので、共有サーバ接続を使用する場合はラージプールを構成するようにして下さい。ラージプールを構成すると、UGAは共有プールではなくラージプールに取るようになります。


たろーちゃんは状況をお客様に説明し、この状態で再度性能テストをしてもらうよう、お願いしました。
後日、性能テストの結果が許容範囲まで改善されたとのことで、無事OKを頂きました。

本当は共有サーバ接続なんて使いたくなかったのですが・・・。
システムは色んな人たちと協力しないと最高のパフォーマンスが出せません。
非協力的な人や会社とは、一緒に仕事したくないですね。。。

 

 

 

 

 

今回の「心臓外科医の術式」いかがだったでしょうか?
SQLの実行以外は、データベースアクセスにおける『空白時間』です。
この『空白時間』は、 StatspackAWR にも出現しない厄介な項目であり、原因の特定まで時間が掛かります。
しかし、『血液検査』をすることで、今回もその兆候に気が付くことが出来ました。
次回も頑張りますので、応援よろしくお願い致します。

一度 V$ACTIVE_SESSION_HISTORY の使い勝手の良さを味わってしまうと、もう抜け出すことが出来ません。
V$ACTIVE_SESSION_HISTORY サイコーです!!

 

 

投稿者プロフィール

たろーちゃん
たろーちゃん
株式会社システムサポート インフラソリューション事業部に在籍するPlatinumホルダー。
Oracle Databaseのパフォーマンスチューニングを得意とする。
データベースは Oracle 以外興味がないという変わり者。
一番嫌いなエラーメッセージは CRS-02625。
連載「心臓外科医の術式」を執筆。