Click here to Skip to main content
15,885,365 members
Articles / Database Development
Tip/Trick

OracleDataReader FetchSize Property

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
25 Jul 2012CPOL1 min read 42.6K   1   6
"Application performance depends on the number of database round-trips to retrieve data. The less round-trips, the better the performance."

Introduction

"Application performance depends on the number of database round-trips to retrieve data. The less round-trips, the better the performance."

Background

Consider an application that loads a big cache of data from database when it starts. A DataReader is a natural choice to do this, since its a set of read-only, forward-only operations.

I observed that to load an Oracle 11g table with 3 million rows and 30 columns the performance increased a lot by reducing the number of round-trips made to provide data to the DataReader.

Using the code

OracleDataReader FetchSize Property

Applications that do not know the exact size of a row at design time can use the FetchSize property of the OracleDataReader object. This FetchSize property should be set after invoking the ExecuteDataReader method of the OracleCommand object and before the first row is fetched using the Read method on the OracleDataReader object.

The RowSize property of the OracleCommand object is set by execution of the ExecuteDataReader. The RowSize property can then be used to set the value of the FetchSize property on the OracleDataReader object. This provides a dynamic way of setting the FetchSize property on the OracleDataReader based on the size of a row:

C#
OracleConnection myConnection = new OracleConnection(myConnectionString);
OracleCommand myCommand = new OracleCommand(mySelectQuery, myConnection);
myConnection.Open();
using (OracleDataReader reader = myCommand.ExecuteReader(CommandBehavior.CloseConnection))
{
    // here goes the trick
    // lets get 1000 rows on each round trip
    reader.FetchSize = reader.RowSize * 1000;

    while (reader.Read())
    {
        // reads the records normally
    }
}// close and dispose stuff here

Points of Interest

I made some experiments using this approach on Oracle 11g database. And I believe that it could bring benefits on other relational databases too.

Reference

http://docs.oracle.com/html/A96160_01/features.htm#1055500.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Brazil Brazil
Yesterday C++, today C#.

Comments and Discussions

 
Question[My vote of 2] Updates Pin
Pregunton Cojonero Cabrón17-Jun-16 7:06
Pregunton Cojonero Cabrón17-Jun-16 7:06 
A number of blogs and sites mention increasing FetchSize of OracleDataReader to improve performance when fetching big volumes of

data (e.g. thousands of rows). There are some documented experiments with exact numbers on this like:

http://metekarar.blogspot.com/2013/04/performance-improvement-for-odpnet.html

Table had a little more than 155K rows and was size of 31 MB. Yet, it took more than 5 minutes to complete for data adapter to fill

data table.

The cause of the problem was the number of round trips client need to accomplish to get all the rows from database. If you can

reduce the number of round trips, you can increase the fetch size so that in each turn command object will fetch more rows from

database. Here is how it's impletemented:

using (OracleConnection conn = new OracleConnection())
{
OracleCommand comm = new OracleCommand();
comm.Connection = conn;
comm.FetchSize = comm.FetchSize * 8;
comm.CommandText = "select * from some_table";
try
{
     conn.Open();
     OracleDataAdapter adap = new OracleDataAdapter(comm);
     System.Data.DataTable dt = new System.Data.DataTable();
     adap.Fill(dt);
}
finally
{
     conn.Close();
}

}

Notice the line with blue font, fetch size of command object increased by 8 times its default which is 128 KB at ODP.Net 11.2.0.3.

OracleDataReader also has the FetchSize property. By increasing fetch size, you increase the cache size in memory to fetch rows.

What we gained is up to 96% performance improvement. Here are some timings with different fetch sizes:

Fetch Size Timing (MI:SS.FF3)
Default (128 KB) 05:20.290
Default x 8 (1 MB) 00:52.941
Default x 32 (4 MB) 00:26.008
Default x 64 (8 MB) 00:12.409

http://metekarar.blogspot.com.es/2013/04/performance-improvement-for-odpnet.html

Strangely, unless the connection pooling is explicitly disabled (e.g. in the connection string), the increase/decrease of FetchSize

stops having any effect. When the pooling is disabled though, it's clear that the FetchSize can improve the performance (the more

records, the bigger the effect).

It turns out that this unexpected behavior is limited to the following conditions: 1) The SELECT statement is exactly the same 2)

The pooling is ON 3) The self-tuning is ON

Only in those conditions the first time the FetchSize is set, it gets somehow cached by ODP.NET and attempts to change it don't

work.
AnswerRe: [My vote of 2] Updates Pin
cesar_boucas17-Jun-16 8:01
cesar_boucas17-Jun-16 8:01 
QuestionOracleDataReader Pin
DavidBTosh19-May-15 22:30
DavidBTosh19-May-15 22:30 
AnswerRe: OracleDataReader Pin
cesar_boucas20-May-15 4:45
cesar_boucas20-May-15 4:45 
GeneralCesar, you the man!!! Pin
Member 1100118112-Dec-14 5:00
Member 1100118112-Dec-14 5:00 
GeneralRe: Cesar, you the man!!! Pin
cesar_boucas12-Apr-16 7:33
cesar_boucas12-Apr-16 7:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.