SqlDataAdapter.Fill метод медленный - PullRequest
31 голосов
/ 30 октября 2008

Зачем хранимой процедуре, которая возвращает таблицу с 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]

Ответы [ 5 ]

47 голосов
/ 30 октября 2008

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

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

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

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

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

Наконец, вы можете попробовать подход " nuke it from orbit " для очистки всего кэша процедур и буферов памяти с использованием SSMS:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

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

5 голосов
/ 29 января 2009

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

Я выполнил следующую инструкцию 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"
2 голосов
/ 06 ноября 2015

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

1 голос
/ 30 октября 2008

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

EDIT:

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

0 голосов
/ 30 октября 2008

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

У вас могут быть проблемы с несовпадением старых версий стека SQL или чем-то подобным (особенно если учесть, что вы, очевидно, застряли и в .NET 1.1). Framework, вероятно, пытается сделать базу данных эквивалентной "Reflection", чтобы вывести схему и т. д. и т. д.

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

...