sql server - SqlDataAdapter.Fill método lento
sql-server vb.net (6)
¿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 declaración 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]
¿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
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 recompilado 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 <databasename>..sp_MSforeachtable @command1=''DBCC DBREINDEX (''''*'''')'', @replacechar=''*''
-- Replace <databasename> 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
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 pila 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.
Tuve el mismo problema y lo solucioné usando este artículo: http://www.databasejournal.com/features/mssql/article.php/3841271/T-SQL-Best-Practices--Parameter-Sniffing.htm