Быстро в SSMS и медленно в приложении - Почему этот DataSet так долго заполняется? - PullRequest
2 голосов
/ 07 февраля 2012

У меня есть набор данных, который заполняется из запроса следующим образом ...

SELECT  DISTINCT ColA, ColB, ColC, ColD, ColE, ColF, dbo.CustomFunction(ColA) AS ColG
FROM    TableA
    JOIN ViewA ON ColA = ViewColA 
WHERE   ColB = @P1 AND ColC = @P2 AND ColD = @P3 AND ColE = @P4 
ORDER BY ColB, ColC DESC, ColA

(Поля запросов и т. Д. Запутаны)

Я профилировал этот запрос, и он возвращает около 200 строкчерез 12 секунд работает в SSMS.Обратите внимание, что я перезапустил сервер и использовал необходимые команды DBCC, чтобы убедиться, что существующий план выполнения не использовался.

Однако, когда я запускаю этот запрос из моего приложения .Net, для заполнения набора данных требуется более 30 секунд ивремя ожидания по умолчанию для команды ADO.Net составляет 30 секунд.

Если запрос выполняется за 12 секунд, я просто не могу понять, почему для заполнения 200 строк в наборе данных требуется более 18 секунд.Если здесь не происходит что-то, о чем я не знаю.Я полагаю, что ADO.Net просто вызывает запрос, получает данные и заполняет их.

Код заполнения выглядит следующим образом (заметьте, я унаследовал это от другого разработчика) ...

DataSet res = new DataSet();

    try
    {
        using (SqlDataAdapter da = new SqlClient.SqlDataAdapter())
        {
            var cmd = new SqlClient.SqlCommand();
            String params = FillParameters(cmd, _params, params);
            cmd.CommandText = params + SQL;
            cmd.Connection = conn;
            cmd.Transaction = _transaction;

            if (CommandTimeout.HasValue)
            {
                cmd.CommandTimeout = CommandTimeout.Value;
            }

            da.SelectCommand = cmd;
            da.Fill(res);
            return res;
        }
    }
    catch
    {
        throw;
    }

Запуск этого в отладке, когда метод заливки срабатывает, метод занимает около 50 секунд.Это подтверждается установкой высокого времени ожидания в команде ADO.Net.Я доволен производительностью запроса, который я могу выполнить последовательно примерно за 12 секунд, так почему же дополнительные 18 с лишним секунд для заполнения набора данных?

Делает ли ADO.Net что-то (возможно, из-за структуры)этот код означает, что для заполнения набора данных требуется более 18 секунд?Я попытался установить для EnforceConstraints значение false, и это не имеет значения.

Одна вещь, на которую следует обратить внимание, состоит в том, что из-за дизайна этой программы в команду sql подается больше необходимого количества параметров.Метод FillParameters делает это.Существует около 20 параметров «по умолчанию», которые добавляются в команду, но в этом запросе используется, например, только 4.

Итак, в итоге,

  • Что может бытьчто для заполнения DS требуется более 18 секунд?

  • Делает ли ADO.Net что-то "умное" с моим набором данных вместо того, чтобы просто выполнить запрос и заполнить набор данных?

  • Может быть, из-за чрезмерного количества переданных параметров возникает проблема.

Спасибо.

Ответы [ 4 ]

2 голосов
/ 08 февраля 2012

Проблема заключалась в том, что существующий код применял уровень изоляции Serializable.

Я сравнивал с помощью SQL Server Profiler команды и статистику выполнения как для запроса, выполняемого через SSMS, так и для приложения.

--- SSMS ---
....
....
set transaction isolation level read committed

CPU: 7797
Reads: 338,425
Writes: 1685
Duration: 7,912

--- Application ---
....
....
set transaction isolation level serializable 

CPU: 46,531
Reads: 241,202
Writes: 0
Duration: 46,792

Затем я выполнил запрос в SSMS, используя оба параметра Set transaction isolution level serializable И exec sp_executesql, чтобы у SQL Server не было подсказок от SSMS относительно содержания запроса.

Это воспроизвело время выполнения 30+секунд и в SSMS, и в приложении.

Это был всего лишь случай изменения кода для использования уровня изоляции Read Committed.

Ссылки: http://www.sommarskog.se/query-plan-mysteries.html#otherreasons

0 голосов
/ 05 октября 2012

Попробуйте ввести SET ARITHABORT ON в вашем запросе.Это действительно решило мою проблему

0 голосов
/ 07 февраля 2012

Я думаю, что ваша проблема не в коде, а в базе данных. Если у вас большая база данных, возможно, это ваша проблема, попробуйте обновить статистику в вашей базе данных, используя следующее:

EXEC sp_updatestats

0 голосов
/ 07 февраля 2012

Предположим, что у ваших таблиц есть первичные ключи

1) проверка фрагментации существующих индексов, если фрагментация превышает 30%, перестройка индекса в противном случае реорганизация 2) проверка отсутствующих столбцов индекса создает некластерные индексы на основе отсутствующих столбцов

Затем перезапустите сценарий sql.Как правило, должно улучшиться после управления правильными индексами.

...