Запрос очень медленный в коде, но быстрый в SSMS - PullRequest
17 голосов
/ 03 октября 2011

У меня довольно простой запрос, который я получаю по таймаутам (это занимает более трех минут, я остановил его раньше, чтобы я мог опубликовать этот вопрос), когда он выполняется в коде, однако когда я выполняю тот же запрос изна том же компьютере в Sql Server Management Studio запрос будет принимать только 2532 ms первый запрос, когда данные не кэшируются на сервере, и 524 ms для повторных запросов.

Вот мой код c #

using (var conn = new SqlConnection("Data Source=backend.example.com;Connect Timeout=5;Initial Catalog=Logs;Persist Security Info=True;User ID=backendAPI;Password=Redacted"))
                using (var ada = new SqlDataAdapter(String.Format(@"
SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 {0}) {1}
Order by dt desc"
     , where.ToString(), (cbShowOnlyFailed.Checked ? "and Status = 1" : "")), conn))
{
    ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID);
    ada.SelectCommand.Parameters.AddWithValue("@dt", dtpFilter.Value);
    //ada.SelectCommand.CommandTimeout = 60;
    conn.Open();
    Logs.Clear();
    ada.Fill(Logs); //Time out exception for 30 sec limit.
}

вот мой код, который я запускаю в SSMS, я вытащил его прямо из ada.SelectCommand.CommandText

declare @clientID varchar(200)
set @clientID = '138'
declare @dt datetime
set @dt = '9/19/2011 12:00:00 AM'

SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 or job_type = 0 or job_type = 1 or job_type = 4 ) 
Order by dt desc

Что вызывает существенное расхождение во времени?


Чтобы сохранить раздел комментариев чистым, я отвечу на некоторые часто задаваемые вопросы здесь.

Один и тот же компьютер и вход в систему используются как для приложения, так и для ssms.

Только 15 строквернулся в моем примере запроса.Однако es_history содержит 11351699 rows, а es_history_dt содержит 8588493 rows.Обе таблицы хорошо проиндексированы, и план выполнения в SSMS говорит, что они используют поиск индекса для поиска, поэтому они являются быстрым поиском.Программа ведет себя так, как будто она не использует индексы для версии запроса на C #.

Ответы [ 4 ]

31 голосов
/ 03 октября 2011

Ваш код в SSMS - это не тот код, который вы запускаете в своем приложении.Эта строка в вашем приложении добавляет параметр NVARCHAR:

 ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID);

, а в сценарии SSMS вы объявляете его как VARCHAR:

declare @clientID varchar(200)

В соответствии с правилами Тип данных Приоритет выражение Where client_id = @clientID в вашем запросе не поддерживает SARG, где @clientID имеет тип NVARCHAR (я делаю прыжок с верой и предполагаю, что столбец client_id имеет тип VARCHAR).Таким образом, приложение вызывает сканирование таблицы, где запрос SSMS может выполнять быстрый поиск ключа.Это хорошо известная и понятная проблема с использованием Parameters.AddWithValue, которая обсуждалась во многих статьях ранее, например.см. Как код доступа к данным влияет на производительность базы данных .Как только проблема понятна, решения тривиальны:

Первое решение лучше, потому что оно решает проблему загрязнения кэша в дополнение к проблеме со способностью SARG.

Я также рекомендовал бы вам прочитать Медленно в приложении, Быстро в SSMS? Понимание загадок производительности

0 голосов
/ 21 мая 2016

Запустите DBCC FREEPROCCACHE, как предложено здесь , просто чтобы убедиться, что проблема не в устаревшем плане выполнения запроса.

0 голосов
/ 04 октября 2011

Захват плана выполнения из обеих SSMS, когда вы запускаете запрос вручную, а затем из Profiler, когда вы запускаете приложение. Сравните и сопоставьте.

0 голосов
/ 03 октября 2011

Запустите профилировщик на вашем соединении c # - могут быть другие действия, о которых вы не знаете.

...