繁体   English   中英

从C#运行时,SQL查询超时,在SQL Server Management Studio中快速

[英]SQL query times out when run from C#, fast in SQL Server Management Studio

我有一个使用下面列出的代码执行SQL查询的C#程序。 我一直在使用此代码一段时间,直到前一天没有问题。

我正在将一个查询字符串传递给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', '05333210', '05348410', '05361110', '05430310',
    '05493710', '05722410', '05849810', '06050510', '06405810', '06738310',
    '07181310', '07373010', '07588710', '07589610', '08143710', '08467070',
    '08651610', '09062X10', '09247X10', '09367110', '09702310', '09972410')

按优先顺序看三件事:

  1. 避免使用AddWithValue()函数 ,因为当ADO.Net猜测列类型错误时,这可能会带来灾难性的性能影响。 做您必须能够为每个参数设置显式数据库类型的操作
  2. 研究OPTION RECOMPILE
  3. 研究未知的优化 仅在其他人失败之后再执行此操作。

您尚未发布查询,但仅基于动态参数列表的构建方式以及大量参数,我将做出猜测并说它与参数嗅探有关-请参阅:

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添加到您存储的proc / option (recompile)以进行查询
  3. optimize for unknown / option (optimize for...针对您的proc /查询option (optimize for...
  4. 其他?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM