SqlDataAdapter.Fill метод медленный

Почему хранимой процедуре, которая возвращает таблицу с 9 столбцами и 89 строками с использованием этого кода, требуется 60 секунд для выполнения (.NET 1.1), если для выполнения в SQL Server Management Studio требуется <1 секунды? Он запускается на локальном компьютере, поэтому задержка в сети незначительна / отсутствует, быстрая машина разработчика

Dim command As SqlCommand = New SqlCommand(procName, CreateConnection())
command.CommandType = CommandType.StoredProcedure
command.CommandTimeout = _commandTimeOut
Try
   Dim adapter As new SqlDataAdapter(command)
   Dim i as Integer
   For i=0 to parameters.Length-1
      command.Parameters.Add(parameters(i))
   Next
   adapter.Fill(tableToFill)
   adapter.Dispose()
Finally
   command.Dispose()
End Try

мой массив параметров набран (для этого SQL это только один параметр)

parameters(0) = New SqlParameter("@UserID", SqlDbType.BigInt, 0, ParameterDirection.Input, True, 19, 0, "", DataRowVersion.Current, userID)

Хранимая процедура - это только оператор выбора, например:

ALTER PROC [dbo].[web_GetMyStuffFool]
   (@UserID BIGINT)
AS
SELECT Col1, Col2, Col3, Col3, Col3, Col3, Col3, Col3, Col3
FROM [Table]

Это старый вопрос, и многие его задают. Прежде чем приступить к очистке кеша и поиграться с настройками ARITHABORT, прочтите исчерпывающую статью Эрланда Соммарскога, в которой объясняется, что может происходить: Медленно в приложении, быстро в SSMS? Понимание тайн производительности Довольно часто такое поведение вызвано функцией SQL Server, которая называется «анализ параметров».

Vladimir Baranov 27.05.2016 02:59

У меня была такая же проблема, и я решил ее исправить с помощью этой статьи: databasejournal.com/features/mssql/article.php/3841271/…

sujeewa 29.09.2010 04:12

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

Kekoa 02.09.2011 20:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
31
3
37 224
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Почему бы не сделать его DataReader вместо DataAdapter, похоже, у вас есть единичный набор результатов, и если вы не собираетесь возвращать изменения в БД и вам не нужны ограничения, применяемые в коде .NET, вы не должны использовать Адаптер.

Обновлено:

Если вам нужно, чтобы это был DataTable, вы все равно можете извлекать данные из БД через DataReader, а затем в коде .NET использовать DataReader для заполнения DataTable. Это должно быть быстрее, чем полагаться на DataSet и DataAdapter.

Код, с которым я работаю, не может возвращать ничего, кроме данных для этого sproc.

Steve Wright 30.10.2008 19:16

Я не знаю, «почему» это так медленно само по себе, но, как указывает Маркус, сравнение Mgmt Studio с заполнением набора данных - это яблоки с апельсинами. Наборы данных содержат много накладных расходов. Я их ненавижу и НИКОГДА не использую, если могу.

У вас могут быть проблемы с несоответствием старых версий стека SQL или некоторых подобных (особенно, если вы явно застряли в .NET 1.1). Framework, вероятно, пытается создать базу данных, эквивалентную «отражению», чтобы вывести схему и т. д. И т. Д.

Одна вещь, которую следует рассмотреть, попробовать с вашим досадным ограничением, - это получить доступ к базе данных с помощью устройства чтения данных и создать свой собственный набор данных в коде. Вы сможете легко находить образцы через Google.

и, пожалуйста, используйте некоторые операторы using, поскольку ваше соединение реализует IDisposable

Ray Booysen 29.01.2009 21:42
Ответ принят как подходящий

Во-первых, убедитесь, что вы правильно профилируете производительность. Например, дважды запустите запрос из ADO.NET и посмотрите, будет ли второй раз намного быстрее, чем в первый раз. Это устраняет накладные расходы на ожидание компиляции приложения и наращивания инфраструктуры отладки.

Затем проверьте настройки по умолчанию в ADO.NET и SSMS. Например, если вы запустите SET ARITHABORT OFF в SSMS, вы можете обнаружить, что теперь он работает так же медленно, как при использовании ADO.NET.

Однажды я обнаружил, что SET ARITHABORT OFF в SSMS вызвала перекомпиляцию сохраненного процесса и / или использование другой статистики. И внезапно и SSMS, и ADO.NET сообщают примерно одинаковое время выполнения.

Чтобы проверить это, просмотрите планы выполнения для каждого запуска, особенно таблицу syscacheobjects. Наверное, они будут другими.

Запуск sp_recompile для определенной хранимой процедуры удалит связанный план выполнения из кеша, что затем дает SQL Server возможность создать, возможно, более подходящий план при следующем выполнении процедуры.

Наконец, вы можете попробовать подход «сбить его с орбиты» для очистки всего кеша процедур и буферов памяти с помощью SSMS:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

Выполнение этого перед тестированием запроса предотвратит использование кэшированных планов выполнения и кеша предыдущих результатов.

DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE решил мою проблему. Нужно ли это запускать периодически или только при внесении изменений в хранимую процедуру?

Merritt 13.08.2009 21:59

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

HTTP 410 15.09.2009 18:52

Отличный ответ, время выполнения моего SP увеличилось с 117 до 3 с! +1

Carl 02.07.2010 23:58

"ВЫКЛЮЧИТЬ АРИТАБОРТ" был отличным ответом! Теперь у меня есть согласованный опыт между ADO.NET и SSMS. В моем случае мне просто нужно было перестроить один индекс, который я сделал из IDE SSMS.

Carter Medlin 22.07.2010 01:31

Да .. DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE решает мою проблему .. но я не хочу очищать кеш для всех объектов в ssms ... могу ли я использовать exec sp_recompile вместо этого для решения этой проблемы. @Дорожный Воин

Munavvar 21.07.2016 10:36

@Munavvar, извините, опоздал, чтобы увидеть ваш комментарий. Да, sp_recompile очистит кеш плана выполнения для указанной хранимой процедуры.

HTTP 410 09.01.2017 17:25

Вот что я в итоге сделал:

Я выполнил следующий оператор SQL, чтобы перестроить индексы для всех таблиц в базе данных:

EXEC <databasename>..sp_MSforeachtable @command1='DBCC DBREINDEX (''*'')', @replacechar='*'
-- Replace <databasename> with the name of your database

Если я хотел увидеть такое же поведение в SSMS, я запускал процедуру следующим образом:

SET ARITHABORT OFF
EXEC [dbo].[web_GetMyStuffFool] @UserID=1
SET ARITHABORT ON

Другой способ обойти это - добавить это в свой код:

MyConnection.Execute "SET ARITHABORT ON"

Я столкнулся с той же проблемой, но когда я перестроил индексы в таблице SQL, он работал нормально, поэтому вы можете подумать о восстановлении индекса на стороне сервера sql.

Другие вопросы по теме