J'ai une requête dans mon application MVC qui prend environ 20 secondes à compléter (à l'aide de NHibernate 3.1). Quand j'exécute la requête manuellement sur le studio de gestion, il faut 0 secondes.
J'ai vu des questions similiaires sur les problèmes similaires à ceux de celui-ci, alors j'ai pris mon test un pas plus loin. P>
J'ai intercepté. La requête utilisant le profileur SQL Server et exécut la requête en utilisant ado.net dans mon application. P>
La requête que j'ai du profileur est quelque chose comme: "EXEC SP_EXECUTSQL N'Sélectionnez ...." << / p>
mon code ado.net: p> Cette requête est également très rapide, ne prenant pas de temps pour exécuter. p> aussi, je J'ai vu quelque chose de très étrange sur le profileur. La requête, lorsqu'elle est exécutée de NH, présente les statistiques suivantes: p> se lit comme suit: 281702
Écrit: 0 P> celui de ADO.NET: reads: 333
Écrit: 0 P> Quelqu'un a un indice? Y a-t-il des informations que je peux fournir pour aider à diagnostiquer le problème? P> Je pensais que cela pourrait être lié à certains paramètres de connexion, mais la version Ado.net utilise la même connexion de NHibernate. P> < p> Merci d'avance p> mise à jour: p> J'utilise NHibernate Linq. La requête est énorme, mais est une requête de pagination, avec seulement 10 enregistrements en cours de récupération. P> Les paramètres transmis au "EXEC SP_EXECUTEQL" sont: P> @ p0 int, @ P1 DateTime, @ p2 DateTime, @ p3 bit, @ p4 int, @ p5 int p> @ p0 = 10, @ p1 = '2009-12-01 00:00:00', @ p2 = ' 2009-12-31 23:59:59 ', @ p3 = 0, @ p4 = 1, @ p5 = 0 p> p>
4 Réponses :
Regardez les paramètres fournis sur le PROP SP_EXECUTESQL stocké. Si les paramètres sont fournis sous forme de NvarchaRar (N'Value ') et des colonnes qu'elles font référence sont Varchar, SQL Server utilisera un plan de requête très inefficace. Cela a été la cause fondamentale de toutes les questions de performance que j'ai eues qui présentent ces symptômes (application lente dans l'application, rapide dans les SSMS). P>
C'est un bon conseil, mais malheureusement non. Les paramètres sont les suivants: @ p0 int, @ P1 DateTime, @ p2 DateTime, @ p3 bit, @ p5 int, @ p5 int ', @ p0 = 10, @ p1 =' 2009-12-01 00:00:00 ', @ p2 = '2009-12-31 23:59:59', @ p3 = 0, @ p4 = 1, @ p5 = 0 "
En outre, dans mon deuxième test, l'application est rapide, mais utilise ADO.NET directement au lieu de NH.
Vous n'avez pas spécifié votre requête ou la taille de ses résultatsset, mais il y a un problème avec la récupération d'un grand nombre d'entités avec NHibernate.
Fondamentalement, le temps de "hydrater" les objets est ce qui prend aussi longtemps.
Vous pouvez essayer d'allumer l'optimiseur de réflexion ou d'utiliser une étanchéité.
Voir Sug suggestions que j'ai ici . P>
En fait, non, car les moments où je comparais sont du profileur SQL Server (la durée de la colonne "), avant que les données soient même hydratées.
J'ai eu l'ADO.NET et NHibernate à l'aide de différents plans de requêtes, et je présentais les effets du paramètre reniflant sur la version NH. Pourquoi? Parce que j'avais déjà fait une requête avec un petit intervalle de date et que le plan de requête stockée a été optimisé pour cela.
Ensuite, lors de l'intervalle d'un intervalle de date limite, le plan stocké a été utilisé et il a fallu des âges pour obtenir un résultat. P>
J'ai confirmé que c'était en fait le problème parce qu'un simple: P >
DBCC FREEPROCCACHE -- clears the query-plan cache
Query = requête.where (true) code> lorsque le résultat attendu était petit (date d'intervalle de date). De cette façon, deux plans de requête différentes seraient créés, un pour les grands ensembles de données et une pour les petits ensembles. LI>
ul> J'ai essayé à la fois des options et a travaillé, mais a opté pour la deuxième approche. C'est un peu hacky em> mais fonctionne vraiment bien i mon cas, car les données sont uniformément distribuées de la date-sage. P> p>
J'aimerais souligner que "DBCC FreeProctacaCaCaCaCaCaCache" efface toute la cache. Cela peut être plus que ce que vous avez négocié dans un système avec beaucoup de choses en cours (SIC Live Environment).
Cette réponse a un exemple de comment utiliser un intercepteur pour ajouter option optimiser pour @P inconnu code> à la fin de la requête.
Plutôt que de modifier la requête, optimiser les index peut également résoudre ce problème. L'ajustement des index devrait être la voie préférée à mon avis. Le paramètre reniflant provoque principalement des problèmes lorsqu'il existe des index inadéquats pour la requête (ou le manque d'index). Mais il est difficile de disposer d'index sonores pour toutes les questions.
J'ai eu le même problème que l'OP. J'ai essayé la suggestion de @ psousa d'injecter une "option (recompilation)" qui a amélioré mes performances. Mais à la fin, j'ai constaté que la simple mise à jour des statistiques sur SQL Server a fait le tour pour moi.
update statistics tablename;
@Skipharris alors fa tellement bonne. Cela a donné une amélioration spectaculaire pour moi _sessionfactory.getCurrentSession (). CreateSeqlQuery ("Mettre à jour les statistiques [Tablez];"). Exécuteuse (); Code>
Utilisez-vous des contrats à terme ou multi-critères dans le code des NIHB?
Essayez d'utiliser NHProf, peut-être que NH émet des autres requêtes par la suite, éventuellement un numéro N + 1.
Bonjour, il n'y a qu'une seule question. J'ai déjà utilisé NHProf
@Firo: Non, pas dans cette requête.
Assez probable paramètre reniflant. Voir "Lent dans l'application, rapide dans SSMS?"
@Martin: Je le fait aussi d'abord, mais mon test Ado.net a également dirigé la même requête de l'application Web, y compris les mêmes paramètres, et il était rapide
@psa - Capturez les plans d'exécution des deux. À peu près sûr, vous découvrirez que pour une raison ou une autre, ils utilisent différents plans.
@Martin: Je l'ai fait, mais ils sont gigantesques. Y a-t-il quelque chose en particulier que je devrais rechercher?
@pousa - Souris sur les flèches du plan lent et recherchez des écarts de gros (ordre de magnitude) entre le nombre réel et estimé de lignes et essayer de tracer ceci à l'opérateur racine. Vous pouvez utiliser Winmerge ou similaire pour comparer le XML pour voir les différences également.
@Martinsmith: Ils étaient en effet différents. Je ne sais pas pourquoi, mais pourrait être lié à l'envoi d'un "sp_executesql" et de l'autre SQL EXEC. Quoi qu'il en soit, ce n'est pas vraiment important car j'ai aussi découvert que c'était bien le paramètre reniflant (comme vous l'avez suggéré), et l'un des plans a été optimisé pour un grand jeu de données et l'autre non. Il s'agissait donc d'une question de résolution du paramètre reniflant sur la requête NH (qui est elle-même digne d'une question de questions). Veuillez poster une réponse avec vos suggestions précédentes afin que je puisse l'accepter.