ejemplo .net sql oracle ado.net oracleclient

.net - dataadapter.fill ejemplo



¿Por qué OracleDataAdapter.Fill() es muy lento? (3)

Estoy utilizando una consulta bastante compleja para recuperar algunos datos de una de nuestras bases de datos de facturación.

Estoy llegando a un problema donde la consulta parece completarse bastante rápido cuando se ejecuta con SQL Developer, pero parece que nunca termina cuando se utiliza el método OracleDataAdapter.Fill() .

Solo intento leer cerca de 1000 filas y la consulta finaliza en SQL Developer en unos 20 segundos.

¿Qué podría estar causando tales diferencias drásticas en el rendimiento? Tengo muchas otras consultas que se ejecutan rápidamente con la misma función.

Aquí está el código que estoy usando para ejecutar la consulta:

using Oracle.DataAccess.Client; ... public DataTable ExecuteExternalQuery(string connectionString, string providerName, string queryText) { DbConnection connection = null; DbCommand selectCommand = null; DbDataAdapter adapter = null; switch (providerName) { case "System.Data.OracleClient": case "Oracle.DataAccess.Client": connection = new OracleConnection(connectionString); selectCommand = connection.CreateCommand(); adapter = new OracleDataAdapter((OracleCommand)selectCommand); break; ... } DataTable table = null; try { connection.Open(); selectCommand.CommandText = queryText; selectCommand.CommandTimeout = 300000; selectCommand.CommandType = CommandType.Text; table = new DataTable("result"); table.Locale = CultureInfo.CurrentCulture; adapter.Fill(table); } finally { adapter.Dispose(); if (connection.State != ConnectionState.Closed) { connection.Close(); } } return table; }

Y aquí está el resumen general del SQL que estoy usando:

with trouble_calls as ( select work_order_number, account_number, date_entered from work_orders where date_entered >= sysdate - (15 + 31) -- Use the index to limit the number of rows scanned and wo_status not in (''Cancelled'') and wo_type = ''Trouble Call'' ) select account_number, work_order_number, date_entered from trouble_calls wo where wo.icoms_date >= sysdate - 15 and ( select count(*) from trouble_calls repeat where wo.account_number = repeat.account_number and wo.work_order_number <> repeat.work_order_number and wo.date_entered - repeat.date_entered between 0 and 30 ) >= 1


Creo que la cultura y la fecha que devuelve su consulta de Oracle son diferentes y es ahí donde la aplicación tarda mucho tiempo en analizar.


Se conocen diferencias de rendimiento entre el uso del proveedor de datos de Microsoft para Oracle y el proveedor de datos Oracle nativo.

¿Has probado ambos?

¿Qué estás tratando de lograr con esta consulta? Olvídate de cosas técnicas, solo el objetivo de todo. Tal vez hay una melodía posible para su consulta.

¿Has probado con un generador de perfiles para ver dónde se atasca?


Este código me ayudó, pruébalo:

using (OracleConnection conn = new OracleConnection()) { OracleCommand comm = new OracleCommand(); comm.Connection = conn; comm.FetchSize = comm.FetchSize * 16; 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(); } }

El trik está en línea (prueba valores de 8 a 64 para encontrar lo mejor para tu caso):

comm.FetchSize = comm.FetchSize * 16;

ACTUALIZAR:

Aquí hay un código mejorado:

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

De aquí