Oracle TimesTen と Hibernate

TimesTen というのは In-Memory Database (IMDB) 製品です.
IMDB というのは文字通りメモリ上に全てのデータを展開して処理する DBMS
ディスクアクセスを前提としてメモリをキャッシュとして使う通常の DBMS よりも速いのが売りなんだとか.
しかも,TimesTen には Cache Connecto to Oracle なんて機能もあって,Oracle Database (10g とか) のキャッシュとして使うなんてこともできるらしい.


今保守してるシステムの処理能力拡大が課題なのですが,もしかして TimesTen を使えるかなぁということで,最近ドキュメント読んだりしてました.
でもでも,TimesTen は Oracle 製品とはいえ,昨年だったか Oracle に買収されたものなので,SQL なんかは Oracle Database とは結構違う模様.
Oracle 方言の外部結合が使えないと困るんだよなぁ.
Oracle 8 時代に作ったシステムだから,標準 SQL (FROM 句に書くヤツ) じゃなくて Oracle 方言で結合しまくってるのだ.DECODE なんかも使いまくり.
それを全部 (数千あるよ) 書き換えるなんてあり得ないったらあり得ません.
そんなわけで (どんなわけで?),仕事で使う見込みはほぼ消えた,と.
っていうか,今の職場は過剰なまでに実績重視な文化で,TimesTen は Oracle さんの提案資料でも押されてないくらいだから,使いたくても使えなかったと思いますけど (苦笑).


でもでも,これはこれでおもしろそう.
別に TimesTen じゃなくてもいいんだけど,IMDB って Hibernate なんかと組み合わせるとよさげかも.
というのも,Java アプリと TimesTen が同じマシンで動いている場合,TimesTen の JDBC ドライバって JNI でダイレクトに共有メモリ上の DB にアクセスするらしいんですよね.
ネットワークも通さないから,SQL の実行時間が数十マイクロ秒とからしい.速っ!!


こうなると結構インパクトあって,従来 DB アクセスを効率的にするにはとにかく SQL の実行回数自体を減らすのが重要で,そのためにたくさん結合したりしてたわけです.
んで,それを効率的に実行してもらうために副問い合わせしまくったりとか.
ところが IMDB だと,SQL の実行回数はあまり重要じゃなくなるかもしれない.
回数増えてもいいから結合しないで単純な SQL にする方が有利になったりするかもしれない.


これは大昔 (メインフレーム時代),今の DB に相当するファイル (ISAM とかじゃなくて DAM ですな) 設計でも似たような話があって,磁気ディスクの場合はアクセス回数を減らすために項目を重複させてでも 1 レコードに多くの情報を乗せていたのに対して,半導体ディスクの場合はアクセス時間よりも転送速度の方がボトルネックだったために,アクセス回数が増えてもいいからレコードサイズを可能な限り小さくする方がお得だったり,みたいな.


もし IMDB でも SQL の実行回数を減らすより結合を控えて結果セットを小さくする方が有利だったら?
Hibernate なんかで注意しなきゃいけないのは Lazy フェッチによる N+1 アクセスですが,それが問題にならないどころか有利になるかもしれない?
さすがにそれはないか.(^^;


ともあれ (JW),面白そうなので Hibernate で遊んでみました.
ありがちな 1 対多の関連を持つ FooBar があり,一つの Foo は複数の Bar と関連づけられています.
もし 10 コの Foo をフェッチして,その先の Bar を Lazy フェッチすると,SQL (SELECT) は 11 回実行されます.
Foo が 100 コなら 101 回,200 コなら 201 回.間違いない.
Lazy フェッチではなく Eager フェッチ (JPA では Join フェッチだっけ?) すれば SQL は 1 回だけ実行されます.
Lazy フェッチと Eager フェッチでどれくらい差があるか (ないか),ちょっとワクワク.
その結果...


ベンチマーク公開禁止だと思うので詳しくは書きませんが,なかなか衝撃的.
Foo が 10 コ,つまり SQL の実行回数が 11 回 (Lazy フェッチ) と 1 回 (Eager フェッチ) だと誤差くらいの違い (数ミリ秒,処理全体の 2% くらい).
Foo が 100 コ,つまり SQL の実行回数が 101 回と 1 回でも 1 割くらいの違い.
Foo が 1000 コ,つまり SQL の実行回数が 1001 回と 1 回でも 2 割くらいの違い.
SQL の実行回数を 1/1000 に減らしても処理速度が 2 割くらいしか速くならないって,今までの感覚だとあり得ないんだけど.
恐るべし TimesTen.恐るべし IMDB
っていうか,Hibernate オーバーヘッド大きすぎ.(^^;


まぁ,そのための 2 次キャッシュって話かもしれないけれど,個人的には 2 次キャッシュより IMDB をキャッシュ代わりに使う方が魅力的な気がします.
2次キャッシュと IMDB はたぶん実装も含めて似てるっぽい.
どちらもレプリケーションや分散トランザクションをサポートしたりとか.
SQL の実行エンジンの有無が大きな違いかな.
あ,Hibernate の問い合わせキャッシュ (2次キャッシュに問い合わせ結果を保持する) も含めるとさらに重なるなぁ.
でもでも,問い合わせキャッシュは同じ SQL で同じパラメータの場合しか効果がないけれど,IMDB は様々な SQL をメモリ上で処理できる分,より広い範囲で効果があるような気のせいがします.
うん,その方がステキ☆ (久々マイリトルシェフ風)


ディスクベースのしっかりした RDBMS と,そのキャッシュとして機能する IMDB を組み合わせたりすると,O/R マッパーを使ってもパフォーマンスで悩む機会が減るかもしれませんね.
O/R マッパーが何をやってるか知らずに使う人が益々増えそうだけど (苦笑).