Weird Timeout Probleme mit Dapper.net

dapper database-performance sql

Frage

Ich habe dapper.net vor einiger Zeit aus Performance-Gründen verwendet und ich mag die benannte Parameter-Funktion im Vergleich zur Ausführung von "ExecuteQuery" in LINQ To SQL.

Es funktioniert gut für die meisten Abfragen, aber ich bekomme von Zeit zu Zeit einige wirklich seltsame Timeouts. Das Seltsamste ist, dass dieses Timeout nur auftritt, wenn das SQL über Dapper ausgeführt wird. Wenn ich die ausgeführte Abfrage, die vom Profiler kopiert wurde, nehme und sie einfach in Management Studio laufe, ist sie schnell und funktioniert perfekt. Und es ist nicht nur ein vorübergehendes Problem. Der Query-Timeout per Dapper ist konsistent und funktioniert in Management Studio durchgängig.

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

Das ist die Abfrage, die ich aus SQL Profiler kopiert habe. Ich führe es so in meinem Code aus.

            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();
        }

Ich habe keine Ahnung, wo ich hier anfangen soll. Ich nehme an, es muss etwas mit Dapper passieren, da es funktioniert, wenn ich nur den Code ausführe.

Wie Sie in diesem Screenshot sehen können. Dieselbe Abfrage wird zuerst über Code und dann über Management Studio ausgeführt.

Bildbeschreibung hier eingeben

Ich kann auch hinzufügen, dass dies nur passiert (ich denke), wenn ich zwei oder mehr Wörter habe oder wenn ich ein "Stop" -Zeichen in der Suchzeichenkette habe. Es kann also etwas mit der Volltextsuche haben, aber ich kann nicht herausfinden, wie man es debuggt, da es perfekt von Management Studio funktioniert.

Und um die Sache noch schlimmer zu machen, funktioniert es gut auf meinem localhost mit einer fast identischen Datenbank sowohl aus Code als auch aus Management Studio.

Akzeptierte Antwort

Dapper ist nichts weiter als ein Utility Wrapper über ado.net; Es ändert nichts an der Funktionsweise von ado.net. Es klingt für mich, dass das Problem hier ist "arbeitet in ssms, scheitert in ado.net". Dies ist nicht einzigartig: Es ist ziemlich üblich, dies gelegentlich zu finden. Wahrscheinliche Kandidaten:

  • "set" -Option: diese haben unterschiedliche Voreinstellungen in ado.net - und können die Leistung beeinträchtigen, insbesondere wenn Sie Dinge wie berechnet + beibehalten + indizierte Spalten haben - wenn die "set" -Optionen nicht kompatibel sind, kann sie entscheiden, dass sie das nicht verwenden kann gespeicherter Wert, daher nicht der Index - und stattdessen Table-Scan und Neuberechnung. Es gibt andere ähnliche Szenarien.
  • Systemlast / Transaktionsisolation - Level / Blockierung; Das Ausführen von etwas in ssms reproduziert nicht die gesamte Systemlast zu diesem Zeitpunkt
  • Cache-Abfragepläne: Manchmal wird ein Duff-Plan zwischengespeichert und verwendet; Das Ausführen von SSMs erzwingt normalerweise einen neuen Plan - der natürlich auf die Parameter abgestimmt ist, die Sie in Ihrem Test verwenden. Aktualisieren Sie alle Ihre Indexstatistiken usw., und überlegen Sie, den Abfragehinweis "Optimieren für" hinzuzufügen

Beliebte Antwort

In ADO ist der Standardwert für CommandTimeout 30 Sekunden in Management Studio infinity. Passen Sie das Befehlstimeout für den Aufruf von Query <> an, siehe unten.

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();
}

Siehe auch SqlCommand.CommandTimeout-Eigenschaft auf MSDN



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow