2010-03-12 236 views
3

我正在使用一個非常複雜的查詢從我們的一個賬單數據庫中檢索一些數據。爲什麼OracleDataAdapter.Fill()非常慢?

我遇到了一個問題,即在使用SQL Developer執行查詢時似乎很快完成查詢,但在使用OracleDataAdapter.Fill()方法時似乎無法完成。

我只是想了解1000行,並且查詢在SQL Developer中在大約20秒完成。

什麼可能導致性能上的巨大差異?我有很多使用相同功能快速運行的其他查詢。


這裏是我用來執行查詢的代碼:

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

這裏是SQL的大綱我使用:

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 
+0

我有類似的SQL Server的問題,但沒有滿意的解決方案。如果您可以運行數據包跟蹤或應用程序跟蹤來比較這兩個查詢,那麼可能會對此有所瞭解。 – dsolimano 2010-03-12 18:37:58

回答

2

有使用Microsoft Data Provider for Oracle和本機Oracle數據提供程序之間的已知性能差異。

你試過了嗎?

你想用這個查詢來實現什麼?忘記技術的東西,只是它的目標。也許你的查詢可能有一個曲調。

你有沒有試過探查器,看看它卡在哪裏?

+0

我使用Oracle的Oracle.DataAccess.dll – 2010-03-12 17:48:03

+1

事實上,'Systm.Data.OracleClient'已在.NET 4中被棄用 - http://msdn.microsoft.com/zh-cn/library/system.data .soleclient(VS.100).aspx – 2010-03-12 17:56:43

+0

所以,在頂部,我有'使用Oracle.DataAccess.Client;' – 2010-03-12 17:59:00

1

我認爲文化和你的Oracle查詢返回的日期是不同的,這是其中應用程序採取了大量的時間來解析。

+0

使用其他查詢使用相同的代碼訪問相同的數據庫服務器運行速度非常快。我已經讓這20秒查詢運行了一晚。我會看看這個... – 2010-03-12 17:52:38

+0

沒有骰子。刪除'table.Locale'調用沒有效果。 – 2010-03-12 18:01:32

1

此代碼幫助我,試試吧:

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

的trik是線(嘗試從8到64個值,找到最適合你的情況下):

comm.FetchSize = comm.FetchSize * 16; 

UPDATE:

下面是一個改進的代碼:

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 

From here

+1

說明如下:http://metekarar.blogspot.com/2013/04/performance-improvement-for-odpnet.html – 2015-10-13 12:32:39

相關問題