Вызов ADO.NET хранимой процедуры T-SQL вызывает исключение SqlTimeoutException - PullRequest
30 голосов
/ 07 мая 2009

У меня есть хранимая процедура T-SQL с подписью

CREATE PROCEDURE MyProc
@recordCount INT OUTPUT
@param1 INT
...

При выполнении непосредственно на Sql Server процедура выполняется менее чем за 5 секунд, возвращая несколько результирующих наборов, всего около 100 строк.

Вызов этой процедуры с использованием метода ADO.NET SqlDataAdapter.Fill для заполнения Dataset вызывает SqlTimeoutException для SqlCommand через 3 минуты (указанный интервал времени ожидания).

Изменение хранимой процедуры таким образом, чтобы она больше не имела выходного параметра и чтобы требуемое выходное значение возвращалось как последний набор результатов, решает проблему, и весь процесс выполняется менее чем за 5 секунд, как и ожидалось.

Но почему?

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

Еще одна вещь, на которую следует обратить внимание, это то, что это очевидно только на одном конкретном сервере, который по общему признанию имеет больший набор данных, чем другие аналогичные базы данных, которые мы используем. Конечно, не настройка сервера Sql?

UPDATE

При входе в исходный код фреймворка проблема заключается в извлечении метаданных. Метод ConsumeMetaData объекта SqlDataReader зависает бесконечно. Однако я запустил тесты на других базах данных и не могу воспроизвести, поэтому это проблема, связанная с базой данных, когда эта процедура вызывается через ADO.NET ... Отлично.

ОБНОВЛЕНИЕ II

Подтвердил, что проблема по-прежнему возникает, если я изменяю код для использования OleDbDataAdapter с типами поставщиков SQLOLEDB или SQLNCLI. Обязательно делать с подключением.

Ответы [ 3 ]

45 голосов
/ 08 мая 2009

Как только я определил, что это корень проблемы ADO.NET в корне проблемы, этот поток привел меня к ответу.

В основном соединения через Sql Server Management Studio (SSMS) по умолчанию имеют SET ARITHABORT ON. ADO.NET соединения нет.

Установка ARITHABORT OFF и выполнение запроса напрямую через SSMS дает мне такое же медленное время ответа.

Основное отличие при работе с этим параметром или без него заключается в том, что для обоих вызовов создается разный план запроса. Когда ARITHABORT было OFF, команда SSMS использовала предварительно скомпилированный план кэшированных запросов, который использовал соединение ADO.NET, и, следовательно, время ожидания.

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

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

Я могу только предположить, что скомпилированный план запроса поврежден или недействителен.

Я воспользуюсь этим решением (я проголосовал против) в другом обсуждении

Спасибо.

1 голос
/ 07 мая 2009

Я исправлен - да, у вас CAN есть оба - параметр OUTPUT, а также набор возвращаемых строк. Вы узнаете что-то новое каждый день: -)

Относительно того, почему происходит тайм-аут - хм .... трудно сказать. Быстрый образец для меня отлично работает. Можете ли вы опубликовать свой сохраненный процесс (по крайней мере, соответствующие биты)?

Сколько строк мы говорим, которые возвращаются сюда?

В какой момент вашего хранимого процесса вы рассчитываете количество строк, которые необходимо вернуть в качестве параметра OUTPUT?

Что если вы попытаетесь добавить еще один параметр MaxRows к вашему одному SProc в качестве теста и выполните SELECT TOP (@MaxRows)....... для ваших данных? Это быстро возвращается?

Марк

0 голосов
/ 24 октября 2016

Короче говоря - я исправил свою проблему, заставив SQL Server использовать наиболее подходящий индекс для ограничения логических чтений lob, когда он не мог понять это самостоятельно.

В длинных -

Я просто столкнулся с этой проблемой и решил ее по-другому, попробовав все остальные предложенные ответы. В SSMS запрос выполнялся в течение ~ 3 с, но время ожидания при вызове из веб-приложения .Net MVC.

Статистический вывод ввода-вывода в SSMS сообщал мне, что в одной таблице было выполнено более 195 500 000 циклических логических операций чтения (таблица с 20М-строками с кластеризованным индексом хранилища столбцов, а также с индексами строк, но без столбцов «LOB»). Из плана выполнения я заметил, что основная часть нагрузки (76%) приходилась на поиск индекса по одному из индексов строки. Я использовал следующее:

from [table] with (index([clustered columnstore index name]))

в моем запросе, чтобы принудительно использовать кластеризованный индекс columnstore, и мой запрос был уменьшен до <1 с, а логическое чтение lob уменьшено до <6k с> 195M, а теперь при вызове SP из веб-приложения происходит округление -отключение в 1,3 с.

Я попытался перекомпилировать опцию, включить arithabort, перехват параметров, и в конце концов SQL Server просто не смог определить, какой индекс использовать. Кстати, это тоже крайний случай, и единственный раз, когда мне приходилось форсировать индекс в этой базе данных.

...