NHibernate Linq Query в 3 раза медленнее, чем HQL - PullRequest
14 голосов
/ 06 июня 2011

У меня есть простой тест, который запускает запрос 5000 раз. Версия запроса linq в 3 раза превышает HQL, а кэшированная версия 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:   Cached: less than a second   No-Cache: 5 seconds
LINQ:  Cached: 8 seconds            No-Cache: 15 seconds

Я просто хочу убедиться, что я испытываю ожидаемые накладные расходы, а не что-то, что я делаю неправильно.

если это накладные расходы есть, и я мало что могу сделать, можете ли вы предложить что-то среднее, что потребует меньше струн, но обеспечит лучшую производительность?

Примечание: Моя настройка кеша в Fluent Nhibernate .Cache(c => c.UseQueryCache().UseSecondLevelCache().UseMinimalPuts().ProviderClass<HashtableCacheProvider>())

1 Ответ

10 голосов
/ 22 июня 2011

Я думаю, проблема в следующем.Этот запрос:

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() оценивается по всем элементам коллекции 1.

Так что если вы попробуете что-то вроде

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

, оно должно вести себя одинаковокак ваш запрос HQL.

...