2013-03-28 11 views
8

Ho iniziato a utilizzare dapper.net qualche tempo fa per motivi di prestazioni e mi piace molto la funzionalità dei parametri denominata rispetto a eseguire semplicemente "ExecuteQuery" in LINQ A SQL.Problemi di timeout strano con Dapper.net

Funziona alla grande per la maggior parte delle query, ma di tanto in tanto ottengo alcuni timeout davvero strani. La cosa più strana è che questo timeout si verifica solo quando SQL viene eseguito tramite dapper. Se prendo la query eseguita copiata dal profiler e la eseguo in Management Studio è veloce e funziona perfettamente. E non sono solo problemi temporanei. La query è costantemente timeout tramite dapper e funziona in modo coerente in 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 

Questa è la query copiata da SQL Profiler. Lo eseguo così nel mio codice.

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

Non ho idea da dove iniziare qui. Suppongo che ci sia qualcosa che sta succedendo con dapper poiché funziona bene quando eseguo il codice.

Come si può vedere in questo screenshot. Questa è la stessa query eseguita prima tramite il codice e successivamente tramite Management Studio.

enter image description here

Posso anche aggiungere che questo solo (credo) succede quando ho due o più parole o quando ho un carattere "stop" nella stringa di ricerca. Quindi potrebbe avere qualcosa da fare con la ricerca di testo completo, ma non riesco a capire come eseguire il debug poiché funziona perfettamente da Management Studio.

E per rendere le cose ancora peggiori, funziona bene sul mio localhost con un database quasi identico sia dal codice che da Management Studio.

risposta

7

Dapper non è altro che un wrapper di utilità su ado.net; non cambia il modo in cui ado.net opera. Mi sembra che il problema qui sia "works in ssms, fail in ado.net". Questo non è unico: è abbastanza comune trovarlo ogni tanto. probabili candidati:

  • "set" opzione: questi hanno differenti valori di default in ado.net - e possono influire sulle prestazioni soprattutto se si hanno cose come calcolato + persisteva + colonne indicizzate - se il "set" opzioni non sono compatibili può decidere che non può usare il valore memorizzato, quindi non l'indice, e invece scansionare e ricalcolare la tabella. Ci sono altri scenari simili.
  • carico di sistema/isolamento livello di transazione/blocco; l'esecuzione di qualcosa in SSM non riproduce l'intero carico del sistema in quel momento
  • piani di query memorizzati nella cache: a volte un piano duff viene memorizzato nella cache e utilizzato; l'esecuzione da ssms di solito impone un nuovo piano, che sarà naturalmente ottimizzato per i parametri che si stanno utilizzando nel test. Aggiorna tutte le statistiche dell'indice ecc. E considera l'aggiunta del suggerimento "ottimizza per" query
+0

Ci dispiace per la mia risposta tardiva ma era un po 'difficile da testare. Comunque penso che abbia a che fare con i piani di query memorizzati nella cache. Ho ottenuto il timeout locale ora e riavviato il server e poi ha funzionato. Ho provato ad aggiungere un "OPTIMIZE FOR" ora. Speriamo che questo possa aiutare. Grazie per gli approfondimenti! – Olaj

6

In ADO è il valore predefinito per CommandTimeout 30 secondi, in Management Studio infinity. Regola il timeout del comando per chiamare la query <>, vedi sotto.

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

Vedi anche SqlCommand.CommandTimeout Property on MSDN