SqlDataAdapter.Fill método lento

¿Por qué un procedimiento almacenado que devuelve una tabla con 9 columnas, 89 filas usando este código toma 60 segundos para ejecutarse (.NET 1.1) cuando lleva <1 segundo para ejecutarse en SQL Server Management Studio? Se está ejecutando en la máquina local con muy poca / sin latencia de red, máquina de desarrollo rápido

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 

mi matriz paramter está tipada (para este SQL es solo un parámetro)

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

El procedimiento almacenado es solo una statement de selección como esta:

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

En primer lugar, asegúrese de que está perfilando el rendimiento de forma adecuada. Por ejemplo, ejecute la consulta dos veces desde ADO.NET y vea si la segunda vez es mucho más rápida que la primera vez. Esto elimina la sobrecarga de esperar a que la aplicación se compile y la infraestructura de depuración aumente.

A continuación, compruebe la configuración predeterminada en ADO.NET y SSMS. Por ejemplo, si ejecuta SET ARITHABORT OFF en SSMS, puede encontrar que ahora funciona tan lento como cuando usa ADO.NET.

Lo que encontré una vez fue que SET ARITHABORT OFF en SSMS causaba que el proceso almacenado fuera recomstackdo y / o que se utilizaran estadísticas diferentes. Y, de repente, tanto SSMS como ADO.NET informaban aproximadamente el mismo tiempo de ejecución.

Para comprobar esto, consulte los planes de ejecución para cada ejecución, específicamente la tabla syscacheobjects. Probablemente serán diferentes.

Al ejecutar ‘sp_recompile’ en un procedimiento almacenado específico, se eliminará el plan de ejecución asociado de la memoria caché, lo que le da la oportunidad a SQL Server de crear un plan posiblemente más apropiado en la siguiente ejecución del procedimiento.

Finalmente, puede probar el enfoque ” Destruir desde la órbita ” para limpiar todo el caché de procedimientos y los búferes de memoria usando SSMS:

 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE 

Hacerlo antes de probar la consulta evita el uso de planes de ejecución en caché y la memoria caché de resultados previa.

Esto es lo que terminé haciendo:

Ejecuté la siguiente instrucción SQL para reconstruir los índices en todas las tablas de la base de datos:

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

Si quería ver el mismo comportamiento en SSMS, ejecuté el proceso de esta manera:

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

Otra forma de eludir esto es agregar esto a su código:

 MyConnection.Execute "SET ARITHABORT ON" 

Me encontré con el mismo problema, pero cuando reconstruí los índices en la tabla SQL, funcionó bien, por lo que es posible que desee considerar la reconstrucción de índice en el lado del servidor sql

¿Por qué no convertirlo en un DataReader en lugar de DataAdapter, parece que tiene un conjunto de resultados singel y si no va a hacer cambios en el DB y no necesita restricciones aplicadas en el código .NET no debería usar el adaptador

EDITAR:

Si necesita que sea una DataTable, puede extraer los datos de la base de datos a través de un DataReader y, a continuación, usar el código .NET en DataReader para llenar una DataTable. Eso debería ser aún más rápido que confiar en DataSet y DataAdapter

No sé “por qué” es tan lento en sí mismo, pero como señala Marcus, comparar Mgmt Studio para llenar un conjunto de datos es de manzanas a naranjas. Los conjuntos de datos contienen MUCHA sobrecarga. Los odio y NUNCA los uso si puedo evitarlo.

Puede estar teniendo problemas con desajustes de versiones anteriores de la stack SQL o algo así (especialmente dado que obviamente está atrapado en .NET 1.1 también). Es probable que el Framework intente hacer una base de datos equivalente de “Reflexión” para inferir esquema, etc. etc. etc.

Una cosa que debe considerar probar con su desafortunada restricción es acceder a la base de datos con un lector de datos y crear su propio conjunto de datos en código. Debería poder encontrar muestras fácilmente a través de google.

Intereting Posts