【问题标题】:Slow performance of SqlDataReaderSqlDataReader 性能缓慢
【发布时间】:2010-10-14 08:46:03
【问题描述】:

我在 MSSMS 中执行了约 2 秒的查询(返回 25K 行)

.NET (sqlReader) 中使用的相同查询执行了几分钟!

我也试过只执行阅读器

(注释了 while 循环中的所有代码,只留下 reader.Read() ) - 还是一样!

知道发生了什么吗?


我不是 DBA,也没有特权使用 Profiler - 会询问我的 DBA 并让所有人知道。

与此同时,我注意到在我正在谈论的 SP 中添加“WITH RECOMPILE”参数后,性能得到了显着提升

所以,从我的角度来看,执行计划似乎就是这种情况...... 你怎么看?

[编辑] 此外,我检查过的是执行以下来自 QA 和 .NET 的查询

select @@options

我的理解是它应该为两个环境返回相同的值。 (如果不是不同的 ex.plans 将被使用) 我说的对吗?

[EDIT2] 我读过(来自http://www.sqldev.net/misc/fn_setopts.htmARITHABOIRT=ON 在 QA 中(在 .NET 中它是关闭的)

是否有人知道如何为每个 .NET 连接强制 ARITHABOIRT=ON?

【问题讨论】:

  • Sql 查询分析器是否揭示了有关该问题的任何提示?
  • EJB:代码不值得发布。即使我们使用纯执行阅读器命令,问题也是一样的(在 MS 帮助中可用)
  • Matt Murrell:我不是 DBA,对 Profiler 了解不多。你能指导在哪里/如何检查这些提示吗?

标签: .net sql-server sql-server-2005 sqldatareader


【解决方案1】:

我将在 SQL Server Profiler 中设置跟踪,以查看从 .NET 代码连接时连接使用的 SET 选项设置,以及 SSMS 中使用的设置。通过 SET 选项设置,我的意思是

ARITHABORT
ANSI_NULLS
CONCAT_NULL_YIELDS_NULL
//etc

查看MSDN 以获取选项表

我之前看到过选项不同的问题(在这种情况下,ARITHABORT)并且性能差异很大。

【讨论】:

    【解决方案2】:

    我有这个问题。在数据库服务器的连接设置中勾选“算术中止”设置。

    【讨论】:

    • 在您的情况下帮助选中或取消选中此选项?
    • 你想这样打开它,MyCommand.CommnadText = "SET ARITHABORT ON; " + MyCommand.CommnadText;
    【解决方案3】:

    此外,查询分析器不会下载大文本或大二进制字段的全部内容。您的 SqlDataReader 可能需要更长时间,因为它会下载完整内容。

    【讨论】:

      【解决方案4】:

      我会检查实际检索需要多长时间。

      例如:

        Private Sub timeCheck()
          'NOTE: Assuming you have a sqlconnection object named conn
      
          'Create stopwatch
          Dim sw As New System.Diagnostics.Stopwatch
      
          'Setup query
          Dim com As New SqlClient.SqlCommand("QUERY GOES HERE", conn)
      
          sw.Start()
      
          'Run query
          Dim dr As SqlClient.SqlDataReader = com.ExecuteReader()
      
          sw.Stop()
      
          'Check the time
          Dim sql_query_time As String = CStr((sw.ElapsedMilliseconds / 1000)) & " seconds"
        End Sub
      

      这将允许您查看阻塞是在检索中还是在读取器的执行中。

      【讨论】:

        【解决方案5】:

        如果您在一个循环中执行阅读器,它会执行很多次,那么请确保您使用的是 CommandBehavior.CloseConnection

            SqlCommand cmd = new SqlCommand();
            SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        

        如果你不这样做,每次循环处理该行时,当它完成并且 rdr 和连接对象退出范围时,连接对象将不会被显式关闭,因此它只会被关闭并释放回来当垃圾收集器终于开始完成它时到池中......

        然后,如果您的循环足够快(很可能),您将用完连接。 (池有它可以生成的最大限制)

        这将导致额外的延迟和延迟,因为代码会不断创建额外的不必要的连接(最多)并等待 GC “赶上”正在使用它们的循环...

        【讨论】:

        • 最初的问题只提到运行一个需要很长时间的查询,没有关于创建大量 SqlConnection 对象并执行大量查询。
        • 老兄,原来的查询提到了一个循环......这个网站上的人怎么了?识别其他人的反应中的每一个小细节不是你的职责。除非有人说错了,否则请让您的 cmets 保持积极的态度。
        • 我认为西蒙的意思是,如果建议的答案与原始问题有关,那就太好了。他是对的,最初的问题与连接无关,它与在 .Read() 循环中执行的代码有关,这意味着只有一个连接。所以从技术上讲,你确实说错了,因为你回答了一个没有被问到的问题。
        • 哦,你是对的......我想我在他的评论中错过了这一点。
        猜你喜欢
        • 2015-01-27
        • 2021-06-04
        • 2016-11-09
        • 2021-06-21
        • 2012-05-11
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多