db4o その24 (クエリ評価モード)

db4oは最新のver6.0以降、クエリの評価モードを変更することが可能になっている。
クエリモードは以下のイディオムで変更する。

Db4o.configure().queries().evaluationMode(QueryEvaluationMode mode);

現在、db4oのクエリ評価モード(QueryEvaluationMode)は以下の3通りが指定可能であることを確認している。

  • Immediate mode イミディエイトモード (QueryEvaluationMode.IMMEDIATE)

db4oにおけるクエリのデフォルトモードであり、何も指定しなければこのモードが選択される。
このモードは文字通りクエリを即座に評価実行しその全ての結果を呼び出し側に返す。クエリ実行時に完全な結果セットが得られるが、クエリがスレッドをブロックする時間と、ヒープの消費量は生成されるクエリ結果の規模に比例する。

  • Snapshot mode スナップショットモード (QueryEvaluationMode.SNAPSHOT)

このモードではクエリの実行時には設定された全てのインデクスをだけを処理しておき(スナップショット)、オブジェクト自体は結果セットの列挙時に評価、取得するモードである。
クエリの実行時にはインデクスだけを処理するためイミディエイトモードに比べて処理待ちが少なく、メモリ消費量も抑えることができる。予め結果を取得するためのインデクスのセットをクエリ時に生成しておくため、後述するレイジーモードで発生する問題は発生しない。

  • Lazy mode レイジーモード (QueryEvaluationMode.LAZY)

このモードはクエリの実行時には何も評価せず、結果セットを処理するイテレータだけを生成しておき列挙時のその結果を取得する。これは、いわゆるRDBアクセス用のミドルウェアで言うところの「サーバサイドカーソル」や「バーチャルモード」と同等であるとされている。クエリは即座にリターンし、その時のメモリの消費量とスレッドのロック時間は最小となる。
と、ここまでは良い所ばかりだがクエリの実行時から結果セットの列挙時までロックをかける訳にはいかないので、クエリ結果はRead Uncommittedと同等の分離性しか持てない。(他のトランザクションの更新の影響を受ける)


このようにクエリモードはかなりその性質が変わるため、デフォルトのイミデイエイトモードを変更する場合は充分な注意が必要だろう。特にレイジーモードには注意であり、db4objectsのドキュメントにもレイジーモードはシングルトランザクション環境で使うことを強く推奨している。

実際に試してみたがクエリモードによる差はデータの件数に合わせて大きくなる傾向がある。例えば3万件程度のオブジェクトが格納されているデータベースに対して複数のフィールドの条件を設定するようなクエリの場合、イミディエイトモードとレイジーモードでは、クエリの実行と結果セットの列挙に要する時間に如実に差が現れることを確認している。