Question

Pourquoi une procédure stockée qui renvoie une table avec 9 colonnes, 89 lignes utilisant ce code prend 60 secondes à s'exécuter (.NET 1.1) lorsqu'elle prend < 1 seconde pour s'exécuter dans SQL Server Management Studio? Il est exécuté sur la machine locale, donc peu ou pas de latence sur le réseau, machine de développement rapide

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

mon tableau de paramètres est tapé (pour ce code SQL, ce n'est qu'un seul paramètre)

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

La procédure stockée est uniquement une instruction select comme celle-ci:

ALTER PROC [dbo].[web_GetMyStuffFool]
   (@UserID BIGINT)
AS
SELECT Col1, Col2, Col3, Col3, Col3, Col3, Col3, Col3, Col3
FROM [Table]
Était-ce utile?

La solution

Tout d’abord, assurez-vous de bien profiler les performances. Par exemple, exécutez la requête deux fois à partir de ADO.NET et voyez si la deuxième fois est beaucoup plus rapide que la première fois. Cela supprime le temps d'attente lié à la compilation de l'application et à la montée en puissance de l'infrastructure de débogage.

Ensuite, vérifiez les paramètres par défaut dans ADO.NET et SSMS. Par exemple, si vous exécutez SET ARITHABORT OFF dans SSMS, vous constaterez peut-être qu'il s'exécute aussi lentement que lors de l'utilisation de ADO.NET.

Ce que j’ai découvert jadis, c’est que SET ARITHABORT OFF dans SSMS entraînait la recompilation du processus stocké et / ou l’utilisation de statistiques différentes. Et soudainement, SSMS et ADO.NET signalaient à peu près le même temps d’exécution.

Pour vérifier cela, examinez les plans d'exécution de chaque exécution, en particulier la table syscacheobjects. Ils seront probablement différents.

L'exécution de 'sp_recompile' sur une procédure stockée spécifique supprimera le plan d'exécution associé du cache, ce qui donnera à SQL Server l'occasion de créer un plan éventuellement plus approprié lors de la prochaine exécution de la procédure.

Enfin, vous pouvez essayer le " le neutraliser en orbite " approche de nettoyage de la totalité du cache de procédure et des mémoires tampons à l’aide de SSMS:

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

Cela avant de tester votre requête empêche l'utilisation de plans d'exécution mis en cache et le cache de résultats précédent.

Autres conseils

Voici ce que j'ai fini par faire:

J'ai exécuté l'instruction SQL suivante pour reconstruire les index sur toutes les tables de la base de données:

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

Si je voulais voir le même comportement dans SSMS, j’exécutais le proc comme suit:

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

Une autre façon de contourner ce problème consiste à ajouter ceci à votre code:

MyConnection.Execute "SET ARITHABORT ON"

J'ai rencontré le même problème, mais lorsque j'ai reconstruit les index sur une table SQL, cela a bien fonctionné. Vous pouvez donc envisager de reconstruire l'index côté serveur SQL

.

Pourquoi ne pas en faire un DataReader au lieu de DataAdapter, il semble que vous ayez un jeu de résultats unique et que si vous n'allez pas reporter les modifications dans la base de données et que vous n'avez pas besoin de contraintes appliquées dans le code .NET, vous ne devriez pas ne pas utiliser l'adaptateur.

EDIT:

Si vous avez besoin que ce soit un DataTable, vous pouvez toujours extraire les données de la base de données via un DataReader puis, dans le code .NET, utilisez le DataReader pour remplir un DataTable. Cela devrait quand même être plus rapide que de compter sur le DataSet et le DataAdapter

Je ne sais pas & "Pourquoi &"; c'est si lent en soi - mais comme le souligne Marcus - en comparant Mgmt Studio au remplissage d'un jeu de données, on compare des pommes à des oranges. Les jeux de données contiennent BEAUCOUP de temps système. Je les déteste et je ne les utilise JAMAIS si je peux l’aider.

Il se peut que vous rencontriez des problèmes avec les différences entre les anciennes versions de la pile SQL ou une autre (en particulier si vous êtes évidemment bloqué dans .NET 1.1 également). Le Framework essaye probablement de résoudre l'équivalent de la base de données de " Reflection " pour déduire un schéma, etc., etc., etc.

Une chose à considérer avec votre contrainte malheureuse est d’accéder à la base de données avec un datareader et de créer votre propre jeu de données en code. Vous devriez pouvoir trouver facilement des échantillons via Google.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top