Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between fetching with server cursor vs streaming

What's the difference, behaviour-wise, between fetching results using server cursors and fetching using streaming?

The former (server cursors) can be activated:

  • For every statement by setting useCursorFetch=true and defaultFetchSize=N in the connection properties. (Where N is a number greater than zero.)

  • Or individual statements by initially setting useCursorFetch=true or com.mysql.jdbc.Connection.setUseCursorFetch(true) on the connection, followed by java.sql.Statement.setFetchSize(N) on the statement.

The latter (streaming) can be activated:

  • On individual statements by setting java.sql.Statement.setFetchSize(Integer.MIN_VALUE) or by calling com.mysql.jdbc.Statement.enableStreamingResults() on the statment.

  • And probably on every statement by setting defaultFetchSize=X in the connection properties, where X is a number equal to Integer.MIN_VALUE.

What does one need to consider when developing with these alternative methods? A good answer may touch on topics such as performance, lock holding, and resource allocation (/ deallocation).

like image 312
antak Avatar asked Sep 17 '15 01:09

antak


People also ask

What is a server side cursor?

A server-side cursor enables a result set to be generated on the server side, but not transferred to the client except for those rows that the client requests. For example, if a client executes a query but is only interested in the first row, the remaining rows are not transferred.

Which command used FOR FETching data from result set?

viewTable , the first column in each row of the ResultSet rs is COF_NAME , which stores a value of SQL type VARCHAR . The method for retrieving a value of SQL type VARCHAR is getString . The second column in each row stores a value of SQL type INTEGER , and the method for retrieving values of that type is getInt .

What is cursor in JDBC?

For a full description of the SQL Server cursor types, see Type of Cursors. The JDBC specification provides support for forward-only and scrollable cursors that are sensitive or insensitive to changes made by other jobs, and can be read-only or updatable.


1 Answers

Examining Mysql's Connector/J source code (v5.1.39):

When using server cursor (setUseCursorFetch(true)) and if the result set type is TYPE_FORWARD_ONLY, it seems like the "streaming" mode is just a special case where the fetched block is 1-row only:

////// RowDataCursor.java /////////

private void fetchMoreRows() throws SQLException {
    ...

    synchronized (this.owner.connection.getConnectionMutex()) {
        ...

        int numRowsToFetch = this.owner.getFetchSize();
        ...

        if (numRowsToFetch == Integer.MIN_VALUE) {
            // Handle the case where the user used 'old' streaming result sets

            numRowsToFetch = 1;
        }

See also MysqlIO.java for the conditions where RowDataCursor is instantiated:

    //
    // Handle cursor-based fetch first
    //

    if (this.connection.versionMeetsMinimum(5, 0, 2) && this.connection.getUseCursorFetch() && isBinaryEncoded && callingStatement != null
            && callingStatement.getFetchSize() != 0 && callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        ServerPreparedStatement prepStmt = (com.mysql.jdbc.ServerPreparedStatement) callingStatement;

        boolean usingCursor = true;

MySQL 5.7 documentation indicates that using server cursor generates a temporary table at the server side (memory table if size allows) so this may affect server performance.

like image 157
nimrodm Avatar answered Sep 27 '22 23:09

nimrodm