views:

346

answers:

2

I am using a pretty complex query to retrieve some data out of one of our billing databases.

I'm running in to an issue where the query seems to complete fairly quickly when executed with SQL Developer, but does not seem to ever finish when using the OracleDataAdapter.Fill() method.

I'm only trying to read about 1000 rows, and the query completes in SQL Developer in about 20 seconds.

What could be causing such drastic differences in performance? I have tons of other queries that run quickly using the same function.


Here is the code I'm using to execute the query:

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;
}

And here is the general outline of the SQL I'm using:

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
+1  A: 

There are known performance differences between using the Microsoft Data Provider for Oracle and the native Oracle Data Provider.

Have you tried both?

What are you trying to achieve with this query? Forget about technical stuff, just the objective of it all. Perhaps is there a tune possible for your query.

Have you tried with a profiler to see where it gets stuck?

Will Marcouiller
I'm using Oracle.DataAccess.dll from Oracle
John Gietzen
In fact, `Systm.Data.OracleClient` has been deprecated in .NET 4 - http://msdn.microsoft.com/en-us/library/system.data.oracleclient(VS.100).aspx
Richard Szalay
So, at the top, I have `using Oracle.DataAccess.Client;`
John Gietzen
Have you tried tuning you query a little more?
Will Marcouiller
Yeah, 20 seconds is down from 300 seconds... Unfortunately, we are talking about a table with tens of millions of rows...
John Gietzen
For sure, it requires time to execute! =P
Will Marcouiller
@Will: Yeah, but I've let it run overnight. I have yet to get any data out of ODAC, but I can get the data just fine using SQL Developer.
John Gietzen
+1  A: 

I think the culture and the date being returned by your Oracle query are different and that is where the application is taking a lot of time to parse.

Angelo
Hitting the same database server with the same code using other queries runs very quickly. I've let this 20 second query run over night. I'll look into this tho...
John Gietzen
No dice. Removing the `table.Locale` call had no effect.
John Gietzen