Время ожидания SQL-запроса при запуске с C#, быстро в SQL Server Management Studio

у меня есть программа c#, которая выполняет SQL-запрос, используя приведенный ниже код. Я использую этот код некоторое время без проблем до недавнего времени.

Я передаю строку запроса в SQL, которая включает список строк, которые являются идентификаторами запасов. Несколько дней назад я запустил его, и запрос истекал, и будет работать больше часа, если я позволю ему. Я провел последние несколько дней, пытаясь отладить это. В моем исходном запросе было около 900 идентификаторов.

Я попытался изменить все, что я могу придумать, и я получаю результаты, которые я не могу объяснить.

например:

  1. запрос работает с одним списком запасов, но не с другим списком той же длины с точки зрения количества строк и общей длины

  2. он работает с одним списком, но не с тем же списком в обратном порядке

  3. С одним списком он работает, если есть ровно 900 идентификаторов, но нет, если есть 899 или 901, и я могу включать или исключать разные идентификаторы и получать те же результаты, поэтому это не что-то фанк с одним из идентификаторов.

в каждом из этих случаев я захватил строку запроса, которая передается моей программой и копируется в SQL Server Management Studio, и в каждом случае запрос выполняется за 1 секунду.

Я прочитал все, что мог на этом и других форумах о запросах, которые работают в управлении SQL Server 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 акций, и это не работает (

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')

2 ответов


три вещи, чтобы посмотреть, в порядке предпочтения:

  1. избегайте использования AddWithValue() функции, поскольку это может иметь катастрофические последствия для производительности, когда ADO.Net угадывает тип столбца неправильно. Сделайте то, что вы должны иметь возможность установить явный тип БД для каждого параметра
  2. посмотреть в ПАРАМЕТР 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 / query
  4. другим?