2009-12-15 6 views
0

Я написал HQL для поддержки ПЕЙДЖИНГАNHibernate HQL производительность подзапроса

  string hql = @"select distinct mr 
         from MediaResource as mr 
         where  mr.Deleted= false 
          and mr.Type = :typeId"; 

      SimpleQuery<MediaResource> q = new SimpleQuery<MediaResource>(hql); 
      q.SetParameter("typeId", typeId); 
      q.SetQueryRange(page * pageSize, pageSize); 
      return q.Execute().ToList(); 

И тогда я написал тест для запуска этой функции и получить NHibernate журнала как

select 
    * 
from 
    (select 
     distinct mediaresou0_.MediaResourceID as MediaRes1_7_, 
    from 
     MediaResource mediaresou0_ 
    where 
     mediaresou0_.Deleted=0 
     and mediaresou0_.Type=:p0) 
where 
    rownum <=:p1; 
:p0 = 1, :p1 = 10 

Что касается меня, является выберите * из (выберите ...) часть. Будет ли это проблемой производительности? Можно ли сообщить Nhibernate для сгенерирования оператора sql только для одного запроса?

ответ

2

Насколько я знаю, это не будет проблемой производительности, если, как упоминалось ddango, не было большого количества строк. Ваш запрос выбирает из подзапроса, а не запускает два отдельных запроса на сервер базы данных, что и делают некоторые люди (и это ужасно для производительности). Вы вернетесь только к правильному набору результатов в конце запроса, я полагаю, что для этого так (с использованием rowcount) должен быть запущен подзапрос.

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

Что касается другого вопроса

Можно ли сказать NHibernate генерировать SQL заявление, чтобы иметь только один запрос?

Я не верю, что NHibernate может быть вызван неявно генерировать более оптимальные решения, единственный способ изменить это изменить способ получения этой информации, но я не вижу никаких проблем с суб -query сам :)

+0

Спасибо за разъяснение. Теперь я чувствую себя намного комфортнее. –

1

Потери производительности, вероятно, не будут заметны, если у вас нет большого количества записей. В этом случае вы будете отбрасывать все записи, а затем берете то, что хотите.

Альтернативой использовать что-то вроде этого:

SimpleQuery<MediaResource> q = new SimpleQuery<MediaResource>(hql); 
     q.SetParameter("typeId", typeId); 
     q.SetFirstResult(page * pageSize).SetMaxResults(pageSize); 
     return q.Execute().ToList(); 

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

SetMaxResults затем работает от этого и получает количество строк в строке размера страницы. (эффективно sql top, где id> xx)

+0

Сначала я не заметил, но поскольку вы используете ActiveRecord, я не уверен, что эти методы выставлены на SimpleQuery. Я думаю, вам может понадобиться использовать session.CreateQuery, как описано здесь: http://www.castleproject.org/ActiveRecord/documentation/v1rc1/usersguide/hql.html – ddango

+0

Спасибо за ответ. Но основная причина, по которой я выбираю ActiveRecord над чистым NHibernate, заключалась в том, что я не хотел испортить сессию. Тем не менее, я рассмотрю коммутатор, как только я почувствую себя более комфортно с работой рамы. –