nhibernate hql子查询性能

时间:2009-12-15 03:01:11

标签: nhibernate hql castle-activerecord

我编写了一个支持分页的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

我关注的是 select * from(select ...)部分。这会是性能问题吗?是否有可能告诉Nhibernate生成sql语句只有一个查询?

2 个答案:

答案 0 :(得分:2)

据我所知,这不会是一个性能问题,除非像ddango提到的那样,存在大量的行。您的查询是从子查询中选择的,而不是对数据库服务器运行两个单独的查询,这是某些人所做的(并且对性能而言非常可怕)。您将只在查询结束时返回正确的结果集,我相信它以这种方式工作(使用rowcount)需要运行子查询。

我的建议是保持原样,如果表格被正确编入搜索索引,你不应该对速度有任何问题,因为查询确实不是那么昂贵,因为它在数据库端完成,它不是就像你实际上将子查询中的每个对象的细节都提取到应用程序并将它们构建到对象中一样。

至于你的其他问题

  

是否可以告诉Nhibernate生成sql语句只有一个查询?

我不相信可以触发NHibernate隐式生成更优化的解决方案,更改此方法的唯一方法是更改​​获取此数据的方法,但我自己看不到子查询的任何问题:)

答案 1 :(得分:1)

除非您有大量记录,否则性能损失可能不会引人注意。在这种情况下,你将撤回所有记录,然后拿走你想要的东西。

另一种方法是使用这样的东西:

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

SetFirstResult将按照其说法执行操作 - 它设置从中继续获取结果的索引。

SetMaxResults然后处理此问题并获取pageSize行数。 (实际上是一个sql top,其中id&gt; xx)