SELECTにより得られた結果セットはどこに
前置き
最近はかなり更新を怠ってますが,それでも見に来ていただいた方ありがとうございます.また少し落ち着いてきたので更新頻度あげるようにがんばります.
てなわけで,本題.
理屈だけでまず考えてみよう.
SELECT文により得られた結果はどこにあるか?
- クライアント側にある.一度の処理で全ての結果セットはクライアント側に送信される.
- サーバ上側ある.クライアント(JDBCドライバ含む)はこれに対して1行ずつ読み込みをかける.
どちらか一方「のみ」がどんな状況でもベターだ,なんてことは無い.
1の問題点.
- 結果が100万行もあったらどうなるか? あるいは結果が100行程度であったとしても、1行あたりのデータサイズが1MBもあったらどうなるか? Javaの場合,ResultSetオブジェクトが超巨大化してJVMのヒープ領域に収まりきらなくなった時点でOutOfMemoryError.
てなわけだが,
2の問題点.
- while句あるいはfor句でループ処理するイメージでいうと,その毎回の処理でネットワークI/Oが発生するためオーバーヘッドがすごくでかい.
- SELECTがロックを使用していた場合,それが解放されるのが遅くなり,同時実行性が低下する.
というのも看過できない.
即ち,結果セットのサイズがクライアント側で扱いきれる範囲内であれば1が良い,そうでなければ2を選択するのが良い,というのが一般的な回答だろう.
2の2個目の問題点について補足.
結果セットとロックの解放の関係
- ロックが解放されるための条件は,トランザクションが完了していること.
- それには即ち,Statementは最低限完了している必要がある.
- Statementが完了するためにはResultSetが完了している必要がある.
この3つ目のやつが関係している.1の場合は気にしなくてOK.でも1行ずつ読み込む場合には全てのデータを読み終えるか,あるいは任意終了するまでStatementも完了とならないのがポイント.
さてMySQL+Connector/Jだけれども.
1がデフォルトで、これまではこの実装のみ.
2はMySQL5.0.3以上+Connector/J3.2.1以上の場合のみ利用可能.
3.2.1以上ですよっ.ってことは3.2以上の安定版でていない今はまだ駄目ってことじゃん.orz