.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í