ODP.Net - OracleDataReader.Read very slow

半世苍凉 提交于 2019-12-02 19:56:21

问题


I'm having a lot of trouble with the OracleDataReader in ODP.Net. Basically, I have a parameterized query that takes anywhere from 1-5 seconds to run (returning around 450 records) and then takes 60-90 seconds to loop over (with no code even running in the loop, literally iterating over the recordset and doing nothing).

When I run it from Aqua Data Studio it takes 1-5 seconds. When I run it from .Net it takes 1-5 seconds for cmd.ExecuteReader() to return. When I loop over the 450 records with OracleDataReader.Read it takes 60-90 seconds to finish.

I even took out all of the code in the loop and just had a blank "While dr.Read" and it still took 60 to 90 seconds to loop over those 450 records (I used a Stopwatch to get the time for the cmd.ExecuteReader and then around the empty dr.Read loop).

I have tried setting the FetchSize, it didn't help (and, it's only 450 records in my test case). I have tried turning auto tuning off with the connection string, it degraded performance even more.

Why is the OracleDataReader.Read taking so long when it's a small amount of data being returned (and other tools return the same data for the same query in a fraction of the time)?

    Using conn As New Oracle.DataAccess.Client.OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings("oracle_dss").ConnectionString)                 
    conn.Open()
    Using cmd As OracleCommand = conn.CreateCommand
        cmd.BindByName = True
        cmd.CommandText = ""  ' removed SQL to make this more readable

        ' Month end
        Dim paramMonthEndDate As OracleParameter = cmd.CreateParameter
        paramMonthEndDate.ParameterName = ":month_end_date"
        paramMonthEndDate.DbType = DbType.Date
        paramMonthEndDate.Value = monthEnd
        cmd.Parameters.Add(paramMonthEndDate)

        Dim sw As New System.Diagnostics.Stopwatch
        sw.Start()

        cmd.FetchSize = 1000
        Dim dr As OracleDataReader = cmd.ExecuteReader
        dr.FetchSize = dr.RowSize * 1000

        sw.Stop()
        Me.Log(String.Format("Month End Query: {0}s", sw.ElapsedMilliseconds / 1000))

        sw.Reset()
        sw.Start()

        While dr.Read

        End While

        sw.Stop()

        Me.Log(String.Format("Month End Query through recordset: {0}s", sw.ElapsedMilliseconds / 1000))

        dr.Close()
            End Using
    conn.Close()
End Using

回答1:


Work with your DBAs and ask them to capture an explain plan for both the stand alone run (aqua data studio) and your odp.net call and confirm they are in fact the same. If they are not, then that will probably explain your problem. You can then try adding "enlist=false" to your connection string but better yet have the DBA's update the statistics on the related tables, hopefully fixing the slow plan. See https://stackoverflow.com/a/14712992/852208 for more info.

I have had this same issue and it came down to oracle being less optimistic about the execution plan when a distributed transaction could be involved.




回答2:


May be I am wrong, but you actually fetch the data in this row: While dr.Read, and not when you are executing the reader. So this can explain why even without doing nothing, dr.Read take all your time.

I'd try to change your command to

1). Run plain sql (without parameters)

2). Run using regular (not binding variable) parameter

3). Move the sql code to Stored Procedure if possible



来源:https://stackoverflow.com/questions/15884433/odp-net-oracledatareader-read-very-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!