2015-03-31 144 views
8

我有一个C#程序,它使用下面列出的代码执行SQL查询。直到有一天,我一直在使用这段代码一段时间没有问题。SQL查询超时从C#运行,在SQL Server Management Studio中快速运行

我将查询字符串传递给SQL,其中包含字符串(库存标识符)列表。前几天我跑了它,查询超时了,如果我让它跑了一个多小时。我花了几天试图调试这个。在我原来的查询中,大约有900个标识符。

我试过改变一切我能想到的,我得到的结果我无法解释。

例如:

  1. 的查询工作与股票的一个列表,但不与相同长度的另一个列表中的字符串,总长度的数量方面

  2. 它与一个列表但不包含相同的列表以相反的顺序

  3. 带有一个列表,它的工作原理是,如果确切地有900个标识符,但没有899或901,我可以包含或排除不同的标识符并获得相同的结果,所以对于其中一个标识符来说这不是一件怪事。

在每一种情况下,我捕捉到正由我的程序通过,并复制到SQL Server Management Studio中的查询字符串,并且在任何情况下,查询在1秒内​​运行。

我已经阅读了本文以及其他论坛上关于在SQL Server Management Studio中工作的查询的所有内容,但是从程序运行时超时,但这看起来不同,因为我可以找到它失败的情况以及类似的情况它不起作用。

我希望能够看到可能发生的事情的建议。

using (SqlConnection conn = new SqlConnection(_connectString)) 
{ 
    conn.Open(); 

    using (SqlCommand cmd = new SqlCommand(queryString, conn)) 
    { 
     cmd.Parameters.Clear(); 
     cmd.CommandTimeout = _timeout; 

     SqlParameter param; 

     if (parms != null) 
     { 
      foreach (string parm in parms.Keys) 
      { 
       param = cmd.Parameters.AddWithValue(parm, parms[parm]); 
      } 
     } 

     SqlDataReader reader = cmd.ExecuteReader(); 

     while (reader.Read()) 
     { 
      QueryResult record = new QueryResult(); 
      record.Fields = new List<object>(); 

      for (int i = 0; i < returnColumns; ++i) 
      { 
       object value = reader.GetValue(i); 

       if (value == DBNull.Value) 
        record.Fields.Add(null); 
       else 
        record.Fields.Add(value); 
      } 

      result.Add(record); 
     } 

     reader.Close(); 
    } 

    conn.Close(); 
} 

这是我的查询。在这个版本中,我包括65个股票,它不起作用(< = 64确实有效)。

select 
    distinct a.Cusip 
, d.Value_/f.CumAdjFactor as split_adj_val 

from qai.prc.PrcScChg a 

join qai.dbo.SecMapX b 
    on a.Code = b.venCode 
    and b.VenType = 1 
    and b.exchange = 1 
    and b.Rank = (select Min(Rank) from qai.dbo.SecMapX where VenCode = a.Code and VenType = 1 and Exchange = 1) 

join qai.dbo.SecMapX b2 
    on b2.seccode = b.seccode 
    and b2.ventype = 40 
    and b2.exchange = 1 
    and b2.Rank = (select Min(Rank) from qai.dbo.SecMapX where SecCode = b.SecCode and VenType = 40 and Exchange = 1) 

join qai.dbo.SecMapX b3 
    on b3.seccode = b.seccode 
    and b3.ventype = 33 
    and b3.exchange = 1 
    and b3.Rank = (select Min(Rank) from qai.dbo.SecMapX where SecCode = b.SecCode and VenType = 33 and Exchange = 1) 

join qai.dbo.DXLSecInfo c 
    on b2.VenCode = c.Code 

join qai.dbo.DXLAmData d 
    on c.Code = d.Code 
    and d.Date_ = @Date 
    and d.Item = 6 

left JOIN qai.dbo.DS2Adj f 
    ON f.InfoCode = b3.VenCode 
    AND f.AdjType = 2 
    and f.AdjDate <= @Date 
    and (f.EndAdjDate >= @Date or f.EndAdjDate is null) 

where 
    a.cusip in ('00101J10', '00105510', '00120410', '00130H10', '00206R10', 
    '00282410', '00287Y10', '00289620', '00724F10', '00817Y10', '00846U10', 
    '00915810', '00936310', '00971T10', '01381710', '01535110', '01741R10', 
    '01849010', '02000210', '02144110', '02209S10', '02313510', '02360810', 
    '02553710', '02581610', '02687478', '03027X10', '03073E10', '03076C10', 
    '03110010', '03116210', '03209510', '03251110', '03265410', '03741110', 
    '03748R10', '03783310', '03822210', '03948310', '04621X10', '05276910', 
    '05301510', '05329W10', '', '05348410', '05361110', '05430310', 
    '05493710', '05722410', '05849810', '06050510', '06405810', '06738310', 
    '07181310', '07373010', '07588710', '07589610', '08143710', '08467070', 
    '08651610', '09062X10', '09247X10', '09367110', '09702310', '09972410') 
+2

我们需要一个查询字符串的例子吗?可以是很多事情,可能需要索引,查询重写等等。 – ibiza 2015-03-31 18:36:58

+0

您需要指定连接字符串中的超时时间(足够长以完成查询) – 2015-03-31 18:37:17

+0

_timeout的值是什么? – UnhandledExcepSean 2015-03-31 18:39:18

回答

6

三件事情来看待,按优先顺序:

  1. Avoid using the AddWithValue() function,因为这可以带来灾难性的性能影响时ADO.Net猜测列类型错误。做你必须能够为每个参数设置一个明确的DB类型
  2. 看看OPTION RECOMPILE
  3. 调查OPTIMIZE FOR UNKNOWN。只有在其他人失败后才能做到这一点。
+0

谢谢,我会试试这些。我也发现周四晚上有一些Windows更新应用到了服务器上(周五我开始有问题),所以我们的IT人员正在研究这些问题。 – freckles 2015-04-01 19:52:46

+0

添加而不是AddWithValue没有帮助(虽然我做了这个改变)。并感谢链接到未知信息的优化,这是非常有用的。我添加了这个选项,它绝对解决了这个问题。谢谢! – freckles 2015-04-01 20:57:18

1

您还没有发布您的查询,但只是基于它是如何被使用的参数的动态列表和参数的数量之多,建,我打算做一个猜测,说有事不带参数的嗅探 - 见:

http://www.brentozar.com/archive/2013/06/the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server/

http://blogs.msdn.com/b/sqlprogrammability/archive/2008/11/26/optimize-for-unknown-a-little-known-sql-server-2008-feature.aspx

问题的基本思想是一组特定的参数,这是非常次优创建一个最佳的查询执行计划换另一套。

有几种方法可以解决参数嗅探问题(幸运的是,其中许多方法在sql server 2008中打开)。

,你可以:

  1. 重构查询
  2. 添加WITH RECOMPILE到您的存储过程/ option (recompile)到您的查询
  3. optimize for unknown/option (optimize for...您PROC /查询
  4. 别人呢?
+1

此外,您可以尝试使用'SET SHOWPLAN_ALL ON查看您的执行计划; '在测试模式下开始查询。在工作查询和非工作查询中以这种方式运行它,看看是否有明显的差异(这种格式有点丑陋,因为它返回的信息表必须经过,与查询管理器不同,但它可以用来找出不一致的地方) – DarrenMB 2015-03-31 18:48:02

相关问题