Problemas de tiempo de espera extraños con Dapper.net

dapper database-performance sql

Pregunta

Empecé a usar dapper.net hace un tiempo por razones de rendimiento y me gusta mucho la función de parámetros nombrados en comparación con ejecutar "ExecuteQuery" en LINQ To SQL.

Funciona muy bien para la mayoría de las consultas, pero de vez en cuando obtengo algunos tiempos de espera muy extraños. Lo más extraño es que este tiempo de espera solo ocurre cuando el SQL se ejecuta a través de Dapper. Si tomo la consulta ejecutada copiada desde el generador de perfiles y solo la ejecuto en Management Studio, es rápida y funciona perfectamente. Y no son solo problemas temporales. La consulta consistentemente expira a través de dapper y siempre funciona bien en 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

Esa es la consulta que copio pegada de SQL Profiler. Lo ejecuto así en mi código.

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

No tengo idea de dónde comenzar aquí. Supongo que debe haber algo que esté sucediendo con dapper, ya que funciona bien cuando solo ejecuto el código.

Como puedes ver en esta captura de pantalla. Esta es la misma consulta ejecutada por código primero y luego a través de Management Studio.

enter image description here

También puedo agregar que esto solo (creo) sucede cuando tengo dos o más palabras o cuando tengo un carácter "detener" en la cadena de búsqueda. Por lo tanto, puede tener algo que ver con la búsqueda de texto completo, pero no puedo descifrar cómo depurarlo, ya que funciona perfectamente desde Management Studio.

Y para empeorar las cosas, funciona bien en mi servidor local con una base de datos casi idéntica tanto del código como de Management Studio.

Respuesta aceptada

Dapper no es más que un contenedor de servicios públicos sobre ado.net; no cambia la forma en que funciona ado.net. Me parece que el problema aquí es "funciona en sms, falla en ado.net". Esto no es único: es bastante común encontrar esto ocasionalmente. Posibles candidatos:

  • Opción "establecer": tienen diferentes valores predeterminados en ado.net y pueden afectar el rendimiento, especialmente si tiene elementos como columnas calculadas + persistentes + indexadas. Si las opciones "establecer" no son compatibles, puede decidir que no puede usar el valor almacenado, por lo tanto, no el índice, y en su lugar escaneo de tabla y recalculo. Hay otros escenarios similares.
  • carga del sistema / nivel de aislamiento de la transacción / bloqueo; ejecutar algo en sms no reproduce toda la carga del sistema en ese momento en el tiempo
  • planes de consulta en caché: a veces un plan duff se almacena en caché y se usa; correr desde sms generalmente forzará un nuevo plan, que naturalmente se ajustará para los parámetros que está usando en su prueba. Actualice todas las estadísticas de índice, etc., y considere agregar la sugerencia de consulta "optimizar para"

Respuesta popular

En ADO es el valor predeterminado para CommandTimeout 30 Seconds, en Management Studio infinito. Ajuste el tiempo de espera del comando para llamar a Query <>, vea a continuación.

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

Consulte también propiedad SqlCommand.CommandTimeout en MSDN



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué