NHibernate中使用延时加载时,语句位置将可能影响性能

nhibernate & .net  NHibernate的强大是毋庸置疑的,但今天在调代码的时候发现一个现象,如果在BL里面调用多次之后,NHibernate会根据逻辑自动生成相应的代码,而且NHibernate的动态SQL是具有位置相关的!如果操作不当,SQL的性能将会大大降低。

  在BL的测试部分代码:

            // HL0
            var lan = _lanRepository.FindByAliasName(lan, host);
/* 通过Id获取分类,调用的是DAL的Repository方法,NHibernate实现*/
            /*忽略中间逻辑*/

            return new PCModel
            {
                /*忽略属性,下面两个关键属性
*/

                // HL1

                PCs = (from pc in lan.Categories
                              select new PCModel { Id = pc.Id, Name = pc.Name }).ToList(),/* HL1:这里也是调用NHibernate实现*/

                // HL2

                Lans = (from l in _lanRepository.FindByDomain(host)
                             select new SLanModel { Id = l.Id, Name = l.Name }).ToList()/*HL2:NHibernate实现*/
            };

上述的HL1和HL2的两个地方都是调用NHibernate实现的,而正是这两个位置,会导致NHibernate生成的动态语句发生变化。

  在使用HL1,HL2的位置顺序时,产生的SQL为(为方便查看,无关的内容已经省略):

HL1:

 exec sp_executesql N'SELECT /*这里省略字段名*/ FROM PCs pcs0_ WHERE pcs0_.LanId=@p0',N'@p0 int',@p0=1

HL2:

exec sp_executesql N'SELECT /*字段名称省略*/ FROM SLans this_ inner join Site s1_ on this_.SiteId=s1_.Id WHERE (s1_.Domain = @p0 or s1_.Domain like @p1 or s1_.Domain like @p2) ORDER BY this_.Id desc',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000)',@p0=N'localhost',@p1=N'localhost
%',@p2=N'%
localhost%'

  可以看到,SQL生成中,HL1的语句非常简单明了,直接通过Id将数据提取出来了。但如果我们将HL1,和HL2的位置对换之后,悲催的事情就出现了。

HL2:

exec sp_executesql N'SELECT /*字段名称*/ FROM SLans this_ inner join Site s1_ on this_.SiteId=s1_.Id WHERE (s1_.Domain = @p0 or s1_.Domain like @p1 or s1_.Domain like @p2) ORDER BY this_.Id desc',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000)',@p0=N'localhost',@p1=N'localhost
%',@p2=N'%
localhost%'

HL1(这里就是lan.Categories):

exec sp_executesql N'SELECT /*字段名称列表*/ FROM PCs pc0_ WHERE pc0_.LanId in (select this_.Id FROM SLans this_ inner join Site s1_ on this_.SiteId=s1_.Id WHERE (s1_.Domain = @p0 or s1_.Domain like @p1 or s1_.Domain like @p2) )',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000)',@p0=N'localhost',@p1=N'localhost
%',@p2=N'%
localhost%'

  从上面的结果非常明显可以看出,lan.Categories是NHibernate 延时加载,NHibernate在我们需要数据的时候,可能帮我做很多的幕后工作,把数据提取到。这的确是个很不错的伙计,默默的在后面帮我们打点好一切。可这个结果却表明,有的时候,这为伙计做到那些工作,却让我们是如此的蛋疼。在查询时,直接对字段的相等比较效率要远远高于后者的LIKE查询,更何况LIKE还是任意位置。我们在延时加载之前,只是调用了一个相关类型的查询工作而已,这伙计愣是把后面本该简单的工作复杂化了。

  这个还只是一个类别,当设计到成千上万的商品的时候,我们如果让NHibernate这位伙计来全权处理的时候,那结果,可能就非常非常的悲催了。这个时候,也许就是你该好好的和NHibernate这位老兄好好沟通的时候了,不然一不小心,我们就要被拉进未知的性能陷阱中。

  所以,在使用NHibernate的时候,我们要时不时的对NHibernate说:嘿,伙计,小心点!

Tuesday, July 24, 2012 | .NET技术 NHibernate

文章评论

No comments posted yet.

发表评论

Please add 7 and 6 and type the answer here:

关于博主

  一枚成分复杂的网络IT分子,属于互联网行业分类中的杂牌军。