Pregunta

¿Por qué un procedimiento almacenado que devuelve una tabla con 9 columnas y 89 filas usando este código tardaría 60 segundos en ejecutarse (.NET 1.1) cuando tarda <1 segundo en ejecutarse en SQL Server Management Studio?Se ejecuta en la máquina local con muy poca o ninguna latencia de red, máquina de desarrollo rápida

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 de parámetros está escrita (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 sólo 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]
¿Fue útil?

Solución

Primero, asegúrese de estar perfilando el rendimiento correctamente.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.Esto elimina la sobrecarga de esperar a que se compile la aplicación y se intensifique la infraestructura de depuración.

A continuación, verifique la configuración predeterminada en ADO.NET y SSMS.Por ejemplo, si ejecuta SET ARITHABORT OFF en SSMS, es posible que ahora se ejecute tan lento como cuando usa ADO.NET.

Lo que encontré una vez fue que SET ARITHABORT OFF en SSMS provocó que se volviera a compilar el proceso almacenado y/o se usaran diferentes estadísticas.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 del caché, lo que luego le dará a SQL Server la oportunidad de crear un plan posiblemente más apropiado en la siguiente ejecución del procedimiento.

Finalmente, puedes probar el "bombardearlo desde la órbita"Enfoque de limpieza de todo el caché del procedimiento y los buffers de memoria usando SSMS:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

Hacerlo antes de probar su consulta evita el uso de planes de ejecución almacenados en caché y caché de resultados anteriores.

Otros consejos

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 evitar 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 del í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 impulsar los cambios en la base de datos y no necesita aplicar restricciones en el código .NET, no debería No use el adaptador.

EDITAR:

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

No sé " ¿Por qué " es muy lento per se, 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.

Es posible que tenga problemas con los desajustes de las versiones anteriores de la pila SQL o algo similar (especialmente dado que obviamente también está atascado en .NET 1.1) Es probable que Framework intente hacer que la base de datos sea equivalente a " Reflexión " inferir esquema, etc., etc., etc.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top