天天看点

[NHibernate]N+1 Select查询问题分析

<a href="http://www.cnblogs.com/wolf-sun/p/4083402.html#t1" target="_blank">写在前面</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4083402.html#t2" target="_blank">文档与系列文章</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4083402.html#t3" target="_blank">n+1 select查询问题分析</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4083402.html#t4" target="_blank">总结</a>

在前面的文章(延迟加载,立即加载)中都提到了n+1 select的问题,总觉得理解的很不到位,也请大家原谅,这也是为什么单独将该问题拿出来做分析的原因。nhibernate的默认lazy加载方式是解决n+1 select问题的一种方案,而我自身的理解是立即加载可以解决,完全的背道而驰了。写出那篇文章后,对这个问题,一直念念不忘,总觉得哪地方不对劲。由于我对问题的理解很不透彻,也同样造成你的误解,真的很抱歉。

<a href="http://www.cnblogs.com/wolf-sun/p/3694592.html">[nhibernate]体系结构</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3694901.html">[nhibernate]isessionfactory配置</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3704012.html">[nhibernate]持久化类(persistent classes)</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3705229.html">[nhibernate]o/r mapping基础</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3720259.html">[nhibernate]关联映射</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3721528.html">[nhibernate]parent/child</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3724052.html">[nhibernate]缓存(nhibernate.caches)</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3734249.html">[nhibernate]nhibernate.tool.hbm2net</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3734313.html">[nhibernate]nullables</a>

<a href="http://www.cnblogs.com/wolf-sun/p/3956802.html">[nhibernate]nhibernate如何映射sqlserver中image字段</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4046672.html">[nhibernate]条件查询criteria query</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4048048.html">[nhibernate]增删改操作</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4049716.html">[nhibernate]事务</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4050714.html">[nhibernate]并发控制</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4067026.html">[nhibernate]组件之依赖对象</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4068749.html">[nhibernate]一对多关系(级联删除,级联添加)</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4070935.html">[nhibernate]一对多关系(关联查询)</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4074654.html">[nhibernate]多对多关系(关联查询)</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4077226.html">[nhibernate]延迟加载</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4082432.html">[nhibernate]立即加载</a>

<a href="http://www.cnblogs.com/wolf-sun/p/4082899.html">[nhibernate]视图处理</a>

使用sql查询数据的时候,如果select太多,势必也会对数据库造成压力,影响性能。比如如果查询n个customer对象,则一次查询获得所有的customer对象,然后根据customerid查询关联的order表。(立即加载的情况下)

一个例子

[NHibernate]N+1 Select查询问题分析
[NHibernate]N+1 Select查询问题分析

这里使用nhinernateutil实用类进行强制立即加载方式,测试代码

查看生成的sql语句

[NHibernate]N+1 Select查询问题分析

本来我们是想查询customer,一次查询就够,可是通过监视到的sql,发现多了一次sql查询,也就是查询customer的关联数据表的数据。

而在延迟加载的情况下,则会在需要的时候才会去查询,性能上面更好。(有关延迟加载的内容,请在系列文章中查找,这里不再赘述了)

如果采用延迟加载方式,生成的sql如下(借用延迟加载文章中的图说明)

一对多关系lazy加载

[NHibernate]N+1 Select查询问题分析

多对多关系lazy加载

order和product多对多关系,此时生成的sql语句

[NHibernate]N+1 Select查询问题分析

你可以看到此时生成的sql语句是通过left outer join(左外连接)进行关联数据表的,而此时只生成一条sql语句,明显减少了查询数据的次数。

(1)select语句的数目太多,需要频繁的访问数据库,会影响检索性能。此时可采用sql中的左外连接查询,在一条sql语句中将所有数据查询出来,并且减少了select的次数。

(2)在应用逻辑只需要访问customer对象,而不需要访问order对象的场合,加载order对象完全是多余的操作,这些多余的order对象白白浪费了许多内存空间。

为了解决以上问题,hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用了sql的外连接查询功能,能够减少select语句的数 

这里就n+1 select问题做一下特别说明,有问题,如果不想办法解决,总觉得有个疙瘩,早解决,早有好心情。通过本篇的分析,你是不是也对n+1的问题豁然开朗?这也怪我了,当时对那一块理解确实有误,再次感到很抱歉。

博客地址:

<a href="http://www.cnblogs.com/wolf-sun">http://www.cnblogs.com/wolf-sun/</a>

博客版权:

本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。

如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!

再次感谢您耐心的读完本篇文章。

转载:http://www.cnblogs.com/wolf-sun/p/4083402.html