MySQL ResultSetのStreamingとCursorの違い
MySQL Connector/J version 8.0の変更点を見ていたら、Configurationsの説明が5.1の時よりも増えていることを見つけました。 その中で、ようやくStreamingとCursorの違いが分かった気がした*1ので備忘メモです。
ResultSetのStreamingとCursor
MySQLでは大きなResultSetの取得にStreamingとCursorの2つの選択肢があります。 version 5.1のマニュアルもversion 8.0のマニュアルも、ResultSet項の説明は一言一句同じです。
Streamingは以下のように、いくつかの属性と setFetchSize(Integer.MIN_VALUE)
を指定することで1行ずつの結果取得を有効化することができます。
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);
この使い方は、Webを検索すれば沢山見つかるのですが、Cursorに関してはストアドプロシージャのカーソルの説明などに埋もれて公式の以下の文章くらいしか中々見つかりません。*2 該当箇所を引用します。
Another alternative is to use cursor-based streaming to retrieve a set number of rows each time. This can be done by setting the connection property useCursorFetch to true, and then calling setFetchSize(int) with int being the desired number of rows to be fetched each time:
説明はこれだけです。 先述のStreamingについては注意事項など、もう少し補足があるのですが、これだけだと何が違うのかよく分かりません。
Configurationsに答えが
ここで冒頭の話に戻って、Configurationsのページを確認すると useCursorFetch
プロパティの説明が補足されていることが分かります。
version 5.1では、
If connected to MySQL > 5.0.2, and setFetchSize() > 0 on a statement, should that statement use cursor-based fetching to retrieve rows?
version 8.0では、
Should the driver use cursor-based fetching to retrieve rows? If set to “true” and “defaultFetchSize” > 0 (or setFetchSize() > 0 is called on a statement) then the cursor-based result set will be used. Please note that “useServerPrepStmts” is automatically set to “true” in this case because cursor functionality is available only for server-side prepared statements.
全然違いますね……。*3
ということで
ざっくりまとめると、次のような感じでしょうか。
- Streaming
- Cursor
- 指定した件数ずつの取得
- DBサーバサイドでプリペアードステートメントを使って制御をする
useServerPrepStmtsはデフォルトfalseとなっているようにtrueにする弊害もある?という感じなのですが、MySQLのIssueでは5.1.38で(一部の?)メモリリークの修正がされたみたいでもあります。結局、プログラマがちゃんと検証しましょう、ということなのでしょう…。*5 基本的には前者のStreamingを使う方がベターな気がします(気がします)。
ちなみにMariaDB Connector/Jは
そもそも useCursorFetch
なんてプロパティはありません。
setFetchSize
で指定したサイズ分で動く分かりやすい挙動になっています。*6
see also:
About MariaDB Connector/J - MariaDB Knowledge Base