Problèmes de délai d'attente étranges avec Dapper.net

dapper database-performance sql

Question

J'ai commencé à utiliser dapper.net il y a quelque temps pour des raisons de performances et j'aime vraiment la fonctionnalité de paramètres nommés par rapport à la simple exécution de "ExecuteQuery" dans LINQ To SQL.

Cela fonctionne très bien pour la plupart des requêtes mais je reçois de temps en temps des temps d'arrêt très étranges. La chose la plus étrange est que ce délai ne se produit que lorsque le SQL est exécuté via dapper. Si je prends la requête exécutée copiée à partir du profileur et que je l'exécute simplement dans Management Studio, c'est rapide et fonctionne parfaitement. Et ce ne sont pas que des problèmes temporaires. La requête expire régulièrement via dapper et fonctionne correctement dans Management Studio.

exec sp_executesql N'SELECT Item.Name,dbo.PlatformTextAndUrlName(Item.ItemId) As PlatformString,dbo.MetaString(Item.ItemId) As MetaTagString, Item.StartPageRank,Item.ItemRecentViewCount
                    NAME_SRCH.RANK as NameRank,
                    DESC_SRCH.RANK As DescRank, 
                    ALIAS_SRCH.RANK as AliasRank, 
                    Item.itemrecentviewcount,
                    (COALESCE(ALIAS_SRCH.RANK, 0)) + (COALESCE(NAME_SRCH.RANK, 0)) + (COALESCE(DESC_SRCH.RANK, 0) / 20) + Item.itemrecentviewcount / 4 + ((CASE WHEN altrank > 60 THEN 60 ELSE altrank END) * 4) As SuperRank
                    FROM dbo.Item
                    INNER JOIN dbo.License on Item.LicenseId = License.LicenseId

                    LEFT JOIN dbo.Icon on Item.ItemId = Icon.ItemId
                    LEFT OUTER JOIN FREETEXTTABLE(dbo.Item, name, @SearchString) NAME_SRCH ON
                    Item.ItemId = NAME_SRCH.[KEY] 
                    LEFT OUTER JOIN FREETEXTTABLE(dbo.Item, namealiases, @SearchString) ALIAS_SRCH ON
                    Item.ItemId = ALIAS_SRCH.[KEY] 
                    INNER JOIN FREETEXTTABLE(dbo.Item, *, @SearchString) DESC_SRCH ON
                    Item.ItemId = DESC_SRCH.[KEY]
                    ORDER BY SuperRank DESC OFFSET @Skip ROWS FETCH NEXT @Count ROWS ONLY',N'@Count int,@SearchString nvarchar(4000),@Skip int',@Count=12,@SearchString=N'box,com',@Skip=0

C'est la requête que je copie collée à partir de SQL Profiler. Je l'exécute comme ça dans mon code.

            using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ToString())) {
            connection.Open();
            var items = connection.Query<MainItemForList>(query, new { SearchString = searchString, PlatformId = platformId, _LicenseFilter = licenseFilter, Skip = skip, Count = count }, buffered: false);
            return items.ToList();
        }

Je n'ai aucune idée par où commencer ici. Je suppose qu'il doit y avoir quelque chose qui se passe avec dapper car cela fonctionne bien quand je viens juste d'exécuter le code.

Comme vous pouvez le voir sur cette capture d'écran. C'est la même requête exécutée via le code d'abord, puis via Management Studio.

entrer la description de l'image ici

Je peux également ajouter que ceci (je pense) seulement se produit quand j'ai deux mots ou plus ou quand j'ai un caractère "stop" dans la chaîne de recherche. Donc, il peut avoir quelque chose à faire avec la recherche en texte intégral, mais je ne peux pas comprendre comment le déboguer car il fonctionne parfaitement à partir de Management Studio.

Et pour aggraver les choses, cela fonctionne très bien sur mon hôte local avec une base de données presque identique à la fois à partir du code et de Management Studio.

Réponse acceptée

Dapper n'est rien de plus qu'une enveloppe utilitaire sur ado.net; cela ne change pas le fonctionnement de ado.net. Il me semble que le problème ici est "fonctionne en ssms, échoue dans ado.net". Ce n'est pas unique: il est assez courant de le trouver occasionnellement. Candidats probables:

  • Option "set": ceux-ci ont des valeurs par défaut différentes dans ado.net - et peuvent avoir un impact sur les performances, en particulier si vous utilisez des colonnes calculées + persistantes + indexées - si les options "set" ne sont pas compatibles, valeur stockée, donc pas l'index - et à la place scan-table et recompute. Il existe d'autres scénarios similaires.
  • charge du système / niveau d'isolation / blocage des transactions; exécuter quelque chose dans SSM ne reproduit pas la totalité du système à ce moment précis
  • plans de requête mis en cache: parfois, un plan de copie est mis en cache et utilisé; courir à partir de ssms forcera généralement un nouveau plan - qui sera naturellement réglé pour les paramètres que vous utilisez dans votre test. Mettez à jour toutes vos statistiques d'index, et envisagez d'ajouter l'indicateur de requête "optimiser pour"

Réponse populaire

Dans ADO est la valeur par défaut pour CommandTimeout 30 Seconds, dans Management Studio infinity. Ajustez le délai de commande pour appeler Query <>, voir ci-dessous.

var param = new { SearchString = searchString, PlatformId = platformId, _LicenseFilter = licenseFilter, Skip = skip, Count = count };
var queryTimeoutInSeconds = 120;
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ToString()))
{
    connection.Open();
    var items = connection.Query<MainItemForList>(query, param, commandTimeout: queryTimeoutInSeconds, buffered: false);
    return items.ToList();
}

Voir aussi Propriété SqlCommand.CommandTimeout sur MSDN




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi