我在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”并且仍然花费60到90秒来循环遍历这450条记录(我使用秒表来获取时间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
答案 0 :(得分:0)
与您的DBA合作并要求他们为独立运行(aqua data studio)和您的odp.net呼叫捕获解释计划,并确认它们实际上是相同的。如果他们不是,那么这可能会解释你的问题。然后,您可以尝试将“enlist = false”添加到您的连接字符串,但更好的是让DBA更新相关表的统计信息,希望能够修复慢速计划。有关详细信息,请参阅https://stackoverflow.com/a/14712992/852208。
我遇到了同样的问题,而且当涉及分布式事务时,oracle对执行计划不太乐观。
答案 1 :(得分:0)
可能是我错了,但你实际上是在获取此行中的数据:While dr.Read
,而不是在执行阅读器时。所以这可以解释为什么即使没有做任何事,dr.Read
也会花费你所有的时间。
我会尝试将您的命令更改为
1)。运行plain sql(不带参数)
2)。使用常规(非绑定变量)参数
运行3)。如果可能,将sql代码移动到存储过程