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 просто не мог понять, какой индекс использовать. Это тоже крайний случай, и единственный раз, когда мне приходилось заставлять индекс в этой базе данных.