2011-06-06 28 views
14

Tengo una prueba simple que ejecuta una consulta 5000 veces. La versión de LINQ de la consulta tarda más de 3 veces el HQL y la versión de LINQ en caché es significativamente más lento que la versión en caché de HQLNHibernate Linq Query es 3 veces más lento que HQL

HQL:

session.CreateQuery(String.Format("from Episode where SeriesId='{0}' and SeasonNumber='{1}' and EpisodeNumber='{2}'", seriesId, seasonNumber, episodeNumber)) 
       .SetMaxResults(1) 
       .SetCacheable(true) 
       .UniqueResult<Episode>(); 

LINQ:

session.Query<Episode>() 
     .Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber) 
     .Cacheable() 
     .FirstOrDefault(); 

Aquí están los resultados

 
HQL: Cached: less than a second No-Cache: 5 seconds 
LINQ: Cached: 8 seconds   No-Cache: 15 seconds 

Solo quiero asegurarme de que estoy sufriendo una sobrecarga y no algo que estoy haciendo mal.

si ese exceso está allí y no hay mucho que pueda hacer, ¿puede sugerir un terreno intermedio que requiera menos cuerdas pero que proporcione un mejor rendimiento?

Nota: Mi configuración de caché en Fluido Nhibernate .Cache(c => c.UseQueryCache().UseSecondLevelCache().UseMinimalPuts().ProviderClass<HashtableCacheProvider>())

+0

¿La instrucción sql generada de la prueba linq 'exactamente' es la misma para todas las iteraciones 5000? – Rippo

+0

No creo que sea la declaración de SQL, ya que la versión en caché que ni siquiera golpea la base de datos es de 8 segundos en comparación con menos de 1. En ambos casos, la base de datos solo se golpea una vez. –

+0

Disculpe, debería haber sido mi punto de vista. ¿Está seguro de que la base de datos solo se muestra una vez para la versión de linq? – Rippo

Respuesta

10

supongo que el problema es el siguiente. Esta consulta:

session.Query<Episode>() 
     .Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber) 
     .Cacheable() 
     .FirstOrDefault(); 

carga todos los episodios de la base de datos, las pone en caché, y luego devuelve la primera instancia de la colección. Cuando se llama al FirstOrDefault, se ejecuta la consulta para Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber) y luego se aplica FirstOrDefault en toda la secuencia devuelta.

Algo así como:

  1. .Where(c => c.SeriesId == seriesId && c.SeasonN... SQL se ejecuta
  2. .FirstOrDefault() se evalúa sobre todos los elementos de la colección de 1.

tanto, si intenta algo así como

session.Query<Episode>() 
     .Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber) 
     .Cacheable() 
     .SetMaxResults(1) 
     .UniqueResult(); 

debería comportarse igual que tu HQL quer y

Cuestiones relacionadas