NHibernate Linq Query в 3 раза медленнее, чем HQL
У меня есть простой тест, который запускает запрос 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
Я думаю, проблема в следующем. Этот запрос:
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
для всей возвращенной последовательности.
Что-то вроде:
-
.Where(c => c.SeriesId == seriesId && c.SeasonN...
Выполняется SQL
-
.FirstOrDefault()
оценивается по всем элементам набора 1.
Итак, если вы попробуете что-то вроде
session.Query<Episode>()
.Where(c => c.SeriesId == seriesId && c.SeasonNumber == seasonNumber && c.EpisodeNumber == episodeNumber)
.Cacheable()
.SetMaxResults(1)
.UniqueResult();
он должен вести себя так же, как ваш HQL-запрос.