ADO.NET, вызывающий хранимую процедуру T-SQL, вызывает исключение SqlTimeoutException
У меня есть хранимая процедура T-SQL с подписью
CREATE PROCEDURE MyProc
@recordCount INT OUTPUT
@param1 INT
...
При выполнении непосредственно на сервере Sql процедура выполняется менее чем за 5 секунд, возвращая несколько наборов результатов, составляющих в общей сложности около 100 строк.
Вызов этой процедуры с использованием метода ADO.NET SqlDataAdapter.Fill
для заполнения Dataset
вызывает SqlTimeoutException
на SqlCommand
через 3 минуты (указанный интервал времени ожидания).
Изменение хранимой процедуры так, чтобы она больше не имела выходного параметра, и что требуемое выходное значение возвращается как последний набор результатов, решает проблему, и все это работает менее чем за 5 секунд, как ожидалось.
Но почему?
Я не хочу проходить свою базу кода и изменять все экземпляры такого типа поведения, не понимая, действительно ли я решил проблему.
Еще одно замечание: это очевидно только на одном конкретном сервере, который, по общему признанию, имеет больший набор данных, чем другие аналогичные базы данных, которые мы запускаем. Наверняка не параметр сервера Sql?
UPDATE
Попадая в исходный код, проблема, похоже, находится в поиске метаданных. Метод ConsumeMetaData
объекта SqlDataReader
висит бесконечно. Однако я запускал тесты в других базах данных и не могу воспроизвести, поэтому это проблема с базой данных, когда эта процедура вызывается, хотя ADO.NET... Отлично.
ОБНОВЛЕНИЕ II
Подтвердили, что проблема все же возникает, если я изменяю код для использования OleDbDataAdapter
с типами SQLOLEDB или SQLNCLI. Определенно делать с соединением.
Ответы
Ответ 1
Как только я определил, что это соединение 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
Я могу предположить, что скомпилированный план запроса стал поврежденным или недействительным.
Я пойду с этим в качестве решения (я проголосовал за ответ) на другой поток
Спасибо.
Ответ 2
Я исправляюсь - да, у вас CAN есть оба параметра - OUTPUT, а также набор возвращаемых строк. Вы узнаете что-то новое каждый день: -)
Что касается того, почему происходит тайм-аут - хм.... сложно сказать. Маленький образец quickie отлично подходит для меня. Можете ли вы опубликовать свой сохраненный proc (по крайней мере, соответствующие его биты)?
Сколько строк мы говорим, которые возвращаются сюда?
В какой момент в вашем сохраненном proc вы вычисляете количество строк, которые должны возвращаться в качестве параметра OUTPUT?
Что делать, если вы попытаетесь добавить еще один параметр MaxRows
в свой SProc как тест и сделать SELECT TOP (@MaxRows).......
в своих данных? Это быстро возвращается?
Марк
Ответ 3
Вкратце - я исправил свою проблему, заставив SQL Server использовать наиболее подходящий индекс для ограничения логических чтений LOB, когда он не мог понять это самостоятельно.
В длинном
Я просто столкнулся с этой проблемой и решил ее по-другому, попробовав все другие предлагаемые ответы. В SSMS запрос выполнялся в ~ 3 с, но был отключен при вызове из веб-приложения .Net MVC.
Статистика IO-вывода в SSMS рассказывала мне, что в одной таблице было более 195 500 000 логических чтений логических элементов (таблица 20M-строк с кластерным индексом столбцов, а также индексы строк, но не содержит столбцов LOB). Я заметил из плана выполнения, что основная часть загрузки (76%) исходила от индекса искать по одному из индексов строк. Я использовал следующее:
from [table] with (index([clustered columnstore index name]))
в моем запросе, чтобы принудительно использовать кластерный индекс столбцов, и мой запрос был уменьшен до < 1s, а логические считывания lob упали до < 6k s > 195M, а при вызове SP из веб-приложения теперь это является круглым отключением в 1.3s.
Я попробовал опцию перекомпилировать, установить arithabort на, sniffing параметра, и в конце SQL Server просто не мог понять, какой индекс использовать. Это тоже крайний случай, и единственный раз, когда мне приходилось заставлять индекс в этой базе данных.