0

我在使用 ODP.Net 中的 OracleDataReader 时遇到了很多麻烦。基本上,我有一个参数化查询,它需要 1-5 秒才能运行(返回大约 450 条记录),然后需要 60-90 秒循环(甚至没有代码在循环中运行,字面上迭代记录集并执行没有什么)。

当我从 Aqua Data Studio 运行它时,它需要 1-5 秒。当我从 .Net 运行它时, cmd.ExecuteReader() 需要 1-5 秒才能返回。当我使用 OracleDataReader.Read 遍历 450 条记录时,需要 60-90 秒才能完成。

我什至取出了循环中的所有代码,只有一个空白的“While dr.Read”,循环这 450 条记录仍然需要 60 到 90 秒(我使用秒表来获取 cmd.ExecuteReader 的时间然后围绕空的 dr.Read 循环)。

我尝试设置 FetchSize,但没有帮助(而且,我的测试用例中只有 450 条记录)。我尝试使用连接字符串关闭自动调谐,它进一步降低了性能。

为什么 OracleDataReader.Read 在返回少量数据时会花费这么长时间(而其他工具在很短的时间内为相同的查询返回相同的数据)?

    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
4

2 回答 2

0

与您的 DBA 合作并要求他们为独立运行(aqua 数据工作室)和您的 odp.net 调用捕获解释计划,并确认它们实际上是相同的。如果他们不是,那么这可能会解释你的问题。然后,您可以尝试将“enlist=false”添加到您的连接字符串,但最好让 DBA 更新相关表的统计信息,希望能修复缓慢的计划。有关更多信息,请参阅https://stackoverflow.com/a/14712992/852208

我也遇到过同样的问题,归结为当可能涉及分布式事务时,oracle 对执行计划不太乐观。

于 2013-04-08T18:47:56.440 回答
0

可能是我错了,但您实际上是在这一行中获取数据: While dr.Read,而不是在执行阅读器时。所以这可以解释为什么即使什么都不做,dr.Read也要花时间。

我会尝试将您的命令更改为

1)。运行普通sql(不带参数)

2)。使用常规(非绑定变量)参数运行

3)。如果可能,将 sql 代码移动到存储过程

于 2013-04-11T04:59:26.293 回答