2009-04-20 3 views
3

j'ai un SqlDataAdapter qui est rempli avec 21 lignes de données (4 colonnes). Le sproc qui le génère est renvoyé dans SQL Mgmt Studio en quelques secondes, mais le fichier .Fill() prend 5 minutes.SqlDataAdapter.Fill() Timeout - Sproc sous-jacente revient rapidement

ArrayList ret = new ArrayList(); 
    SqlDataAdapter da = null; 
    SqlCommand cmd = null; 
     cmd = base.GetStoredProc("usp_dsp_Stuff"); //Returns immediately in MSSMS. 
     cmd.CommandTimeout = 3600; // Set to 6 min - debug only 
     base.AddParameter(ref cmd, "@Param1", ParameterDirection.Input, SqlDbType.BigInt, 8, 19, 0, theParam1); 
     base.AddParameter(ref cmd, "@Param2", ParameterDirection.Input, SqlDbType.BigInt, 8, 19, 0, theParam2); 
     base.AddParameter(ref cmd, "@Param3", ParameterDirection.Input, SqlDbType.Char, 1, 'C'); 
     da = new SqlDataAdapter(cmd); 
     DataTable dt = new DataTable(); 
     da.Fill(dt); //Takes 5 minutes. 

Des idées?

Merci d'avance! -Chris

Répondre

0

Fill() peut parfois être lent parce que .NET est l'analyse des données qui revient de la procédure.

Utilisez le Générateur de profils SQL pour travailler ce qui envoie réellement SQL .NET lorsque le remplissage() exécute.

Si elle envoie beaucoup d'instructions SET, comme

 
set concat_null_yields_null on 
set cursor_close_on_commit off 
set implicit_transactions off 

etc... 

.. puis mettre ces mêmes déclarations ensemble dans votre procédure stockée peut accélérer les choses.

2

Merci pour votre aide. La solution à c'était d'ajouter des déclarations (de NOLOCK) sur les jointures que le sproc utilisait:

DE category_tbl c INNER JOIN dbo.categoryItem_LNK cl AVEC (NOLOCK) SUR c.categoryid = cl.categoryid

Je ne sais pas pourquoi nous ne voyions que la dégradation lors de l'utilisation de SqlDataAdapter, mais cela a changé le problème tout de suite.

Merci encore, Chris

+0

Cela a fonctionné pour moi aussi, je recevais un temps même après avoir tiré 10 enregistrements de la fonction d'une valeur de table. – Sergey

+0

J'ai eu le même problème en cours d'exécution d'une requête, mais en utilisant "WITH (NOLOCK)" n'a pas aidé. Ajouter "OPTION (RECOMPILE)" à la fin de ma requête a résolu le problème. – sharpguru

1

Je déteste briser les nouvelles, mais (NOLOCK) n'est pas une solution, il crée simplement new problems, comme lit sale, manquant/données dédupliquées et même les requêtes avortées. Les verrous dans une base de données SQL sont vos amis.

Si le verrouillage (ou pire, le blocage) était à l'origine à être lent, vous comparez les options de connexion en cours d'exécution par SSMS et ceux utilisés par votre application. Utilisez SQL Profiler pour voir comment le code est en cours d'exécution.

Si l'un de ces champs sont de grands objets, gardez à l'esprit que SSMS récupère automatiquement seulement quelques centaines de caractères par défaut. Les données supplémentaires renvoyées pourraient être un facteur.

+0

En réalité, cela dépend du cas d'utilisation. Peut-être pourriez-vous développer «cela crée simplement un nouveau problème» pour aider le lecteur à décider si ces problèmes sont suffisamment graves pour susciter des inquiétudes dans son propre cas d'utilisation. – Dan

0

Mauvais plans de requête et reniflage de paramètres. Pour un proc stocké, et en particulier un où les paramètres ajusteront sauvagement les rangées lues, un mauvais plan d'exécution de regarder les paramètres entrants est la cause. Cela ne se produit pas dans SQL Management Studio en raison de paramètres SET différents.

Ce fil résume votre question bien: http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/9fd72536-f714-422a-b4c9-078e2ef365da/

C'est un cas typique de renifler des paramètres . Votre application s'exécute probablement avec différentes options SET (définir par l'API client) et utilise un plan d'exécution différent de que celui créé dans SSMS. Ce qui se passe est quand votre procédure Invoke la première fois via votre application est crée plan d'exécution en fonction des paramètres passés.Toutefois, ce plan d'exécution peut ne pas être bon pour un autre jeu de paramètres , ce qui peut entraîner des performances médiocres lorsqu'il est exécuté avec l'autre jeu de paramètres . Voir la suivante pour plus de détails et différentes solutions: http://pratchev.blogspot.com/2007/08/parameter-sniffing.html

Voici plus sur le fonctionnement interne de la mise en cache du plan et la réutilisation du plan de requête:
http://technet.microsoft.com/en-us/library/cc966425.aspx

3

je sais que ce ne soit trop tard, comme 7 années trop tard! mais je me suis heurté à ce problème aujourd'hui et je voulais partager ma solution. Dans mon cas, les données extraites de SQL étaient une fonction de valeur de table. La fonction de valeur de table renvoyait seulement environ 3500 lignes et prenait moins d'une seconde, mais elle expirait sur Fill() dans le code C#. Je ne sais pas qui ou comment cela fonctionne mais la suppression et la recréation de la fonction l'ont corrigé. Je pense que c'est quelque chose à voir avec la façon dont .NET lit les données fournies par SQL, comme la façon dont une vue est nécessaire pour être recréée si vous y apportez des modifications après qu'elle a été utilisée dans un rapport. Encore une fois je, ne suis pas sûr à 100% ce qu'il se passe dans les coulisses, mais ce fut pour moi une solution rapide

+0

Cela a résolu pour moi. Avait un appel de fonction au début de mon sp que les paramètres de date «planchers» et «plafonds». J'ai enlevé la fonction et j'ai fait le «plancher» et le «plafond» manuellement, et cela a fonctionné. –

+0

Il s'avère que la simple suppression et la recréation de la procédure stockée dans notre cas ont corrigé ce problème. Juste pour la sécurité, nous nous sommes assurés (NOLOCK) était inclus partout. Le bogue de SQL Server maintenant - Meilleur à utiliser MongoDB – sean2078

1
da = new SqlDataAdapter(cmd); 
da.SelectCommand.CommandTimeout = 1800; 
+1

S'il vous plaît voir ce premier [how-to-answer] (https://stackoverflow.com/help/how-to-answer) –