導入
Oralce の SGA には共有プールの領域がある。共有プールと言っても、実態はメモリ領域であり、その中には色んな要素が格納される。親・子カーソルはその一例だし、SQL Text や、オブジェクトの情報、PL/SQL の情報など、本当に多岐に渡る。
ポイントは
- 共有プールに格納されるデータは、そのデータごとにサイズが大きく異なる
- サイズどころか、存続期間も大きく異なる
- 共有プールのサイズには(一般に)上限がある
ということにある。
サイズと存続期間が大きく異なるようなものを 1 つのメモリ領域に詰め込んだ場合、発生するのは断片化である。要するに、空き領域はまだあるにも関わらず、それらの空き領域が細ぎれになって散らばっているために、本来格納すべきデータが共有プールに格納できなくなる。格納できないと、Oracle は共有プールの内部的なフラッシュが行われたり、それでも足りないと ORA エラーを吐く。
フラッシュでうまくいったーで喜ぶわけにも行かず、このフラッシュを実行するとき、Oracle は内部的に、他セッションが共有プールを使用しないように内部的なロック(shared pool latch) を取得する。最悪のケースでは、この内部的ロックによって他セッションが待ちになり、DB が一時的にハングアップしてしまう。
メモリ領域に大きさや存在期間の異なるデータを詰め込むときの問題というと、JVM にも同様の問題がある。JVM はこれを世代別 GC によって、解決とは行かないまでも、緩和することに成功している。実は Oracle にも同様の機構が存在していて、それが共有プールの分割になる。
共有プール分割
共有プールの分割の目的は大きく 2 つあると理解している。
- ロック(shared pool latch)の粒度を細かくすることによって、分割された一領域(サブプール)がロックされても、他領域はロックされないようにする
- 共有プールに格納するデータの存続期間毎に領域を分けることで、断片化をできるだけ避けられるようにする
この情報、Oracle の公式マニュアルにはなかなか見つからないんだけど、
Oracle9i以降からは、共有プールをいくつかのサブ・プール(最大7個まで)で分けて管理することができます。 _KGHDSIDX_COUNT隠しパラメータを利用すればサブ・プール数を管理することができます。 OracleはCPU数が4以上で、共有プールの大きさが250MB以上の場合、_KGHDSIDX_COUNT値の数だけサブ・プールを生成し、共有プールを管理します。 サブ・プールは独立的な共有プールとして管理されており、独自の空きリスト、LRUリスト、共有プール・ラッチを持ちます。 従って、共有プールが大きい場合にはサブ・プールを分けて管理することによって共有プール・ラッチ競合を減らすことができます。
http://www.ex-em.co.jp/exem_labo/oracle_knowledge/latch_shared_pool.html
Oracle Database 10gR2からは、自動メモリ管理(自動共有メモリ管理)を使用すると内部的に断片化の発生を抑止するように管理してくれます。共有プールをサイズによって、いくつかのヒープ(サブプール)に分割して使用しています。このサブプールごとに同等の存続期間になるようにして断片化を防止しています。「共有プールの断片化」のところで解放時期が指定できないので断片化が発生すると説明しましたが、それを解消することができる訳です。
技術リソース | Oracle 日本
(中略)
Oracle9i以上からは共有プールをいくつかのサブ・プール(最大7個まで)に分けて管理することができます。 _KGHDSIDX_COUNT隠しパラメータを利用すればサブ・プール数を管理することができます。 OracleはCPU数が4以上で、共有プールの大きさが250MB以上の場合、 _KGHDSIDX_COUNT値の数だけサブ・プールを作って共有プールを管理します。 サブ・プールは独自の共有プールで管理されており、独自の空きリスト、 LRUリスト、共有プール・ラッチを持ちます。 従って、共有プールが大きい場合には、サブ・プールに分けて管理することをお勧めします。 こうすることで共有プール・ラッチ競合を減らすことができます。
とかでその情報が確認できる (上記に挙げた両社は、ともに Oracle 関係で有名)
現在の IT システムで DB サーバにマルチコア CPU を使わないなんてことはないと思うんだけど、そういうシステムでは基本的に共有プールが分割されている。
共有プールがいくつに分割されているのか、といった話は (保守契約を結んでいるのであれば) Oracle に問い合わせれば教えてくれるとおもいます。