【问题标题】:ODP.Net - OracleDataReader.Read very slowODP.Net - OracleDataReader.Read 很慢
【发布时间】:2013-04-11 12:59:26
【问题描述】:

我在使用 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

【问题讨论】:

  • 你能显示你的代码吗..也许你正在做一些打开和关闭连接的事情,基本上往返太多了,但如果没有看到任何现有代码就无法判断。您是否还查看了查询是否为Hitting the Indexes(如果您正在查询的表上有)
  • 让我得到我的代码,我会更新问题。它已编入索引.. 它在 Aqua Data Studio(第三方查询实用程序)中运行完成,所有结果在几秒钟内返回。我认为如果索引不起作用,那也将是相当慢的。
  • 您确定服务器响应时间吗? oracle配置也可能有问题。
  • SQL 数据读取器更快,但差别很大。
  • 我已经用秒表计时了 .Net 代码的每一行,并且我刚刚读取了第 3 方实用程序的执行时间(然后滚动它的数据网格以验证所有数据在那里)。

标签: .net vb.net oracle odp.net


【解决方案1】:

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

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

【讨论】:

  • 我会去看看他们是否可以同时捕获两者(另外,我之前已经在我的连接字符串中添加了 enlist=false 今天)。
  • 什么是让 Oracle 变得不那么乐观的例子?好奇我是否正在做一些我没有意识到的事情来触发它。
  • 显然(来自链接文章中的帖子),仅具有分布式连接的可能性就足够了(这是连接的默认设置)。就我而言,我实际上是在 TransactionScope 的上下文中做事,但论坛上的预言机专家表示这甚至不是必需的。一旦我意识到计划不同,更新统计数据就解决了这个问题。也许是运气。关键是 oracle 为一个连接计算的执行计划可能与另一个不同,因此在 odp.net 之外运行原始查询不一定会原谅数据库。
【解决方案2】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    相关资源
    最近更新 更多