NHibernate Linq查询比HQL慢3倍。

14

我有一个简单的测试,运行一个查询5000次。使用linq版本的查询所需时间是HQL的3倍以上,而缓存的Linq版本比缓存的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();

这里是结果

HQL:   缓存:不到一秒    无缓存:5秒钟
LINQ:  缓存:8秒钟       无缓存:15秒钟

我只是想确认一下,我正在经历一些预期的开销,而不是我做错了什么。

如果有这样的额外负担,并且我没有太多可以做的事情,您能否建议一种折中方案,需要较少的字符串但提供更好的性能?

注意: 我的Fluent Nhibernate缓存设置为 .Cache(c => c.UseQueryCache().UseSecondLevelCache().UseMinimalPuts().ProviderClass<HashtableCacheProvider>())


我认为问题不在SQL语句上,因为缓存版本甚至没有访问数据库就需要8秒,而非缓存版本少于1秒。在两种情况下,只访问了一次数据库。 - kay.one
我注意到第一名仅存在于HQL查询中。LINQ查询很可能是在查询完成后获取第一个结果。你可以检查一下吗? - Pedro
你比较过生成的 SQL 语句是否完全相同吗? - cremor
有趣...请展示Linq为您生成的SQL语句 - Anubis
你可以使用SQL分析来查看使用了哪些SQL语句。你将能够看到这两个查询是否仅返回一个记录,或者第二个查询返回一组记录。然后只在应用程序中获取第一个记录。 - Peter
显示剩余3条评论
1个回答

10

我猜问题在于以下内容。这个查询:

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

从数据库加载所有剧集并将它们放入缓存,然后返回集合的第一个实例。当调用 FirstOrDefault 方法时,查询表达式 Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber) 将被执行,然后 FirstOrDefault 方法将应用于返回的整个序列。

执行过程如下:

  1. 执行 .Where(c => c.SeriesId == seriesId && c.SeasonN... SQL 查询;
  2. 在集合中的所有元素上评估 .FirstOrDefault() 方法。

因此,如果您尝试这样做:

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

它应该像你的HQL查询一样运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接