[NHibernate]N+1 Select查询问题分析
发布日期:2021-08-29 19:53:22 浏览次数:6 分类:技术文章

本文共 2434 字,大约阅读时间需要 8 分钟。

目录

写在前面

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

文档与系列文章

 

 

 

N+1 Select查询问题分析

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

一个例子

1         ///  2         /// NHibernateUtil方式,立即加载客户信息及关联的数据 3         ///  4         ///  5         /// 
6 public Customer GetCustomerByImmediatelyLoadNHibernateUtil(Guid customerID) 7 { 8 //获得ISession实例 9 //通过using的方式将session释放,为了保证是立即加载的数据,而不是延迟加载的10 //还记得上篇文章中提到的在延迟加载中,在关闭session情况下,再读取数据的时候就会有一个异常信息11 //忘记的可以再回到上一篇文章进行查看12 using (ISession session = NHibernateHelper.GetSession())13 {14 Customer customer = session.Get
(customerID);15 //16 // 摘要: 17 // Force initialization of a proxy or persistent collection.18 //19 NHibernate.NHibernateUtil.Initialize(customer.Orders);20 return customer;21 }22 }

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

1         protected void btnImmediately_Click(object sender, EventArgs e)2         {3             Business.CustomerBusiness customerBusiness = new Business.CustomerBusiness();4             Customer customer = customerBusiness.GetCustomerByImmediatelyLoadNHibernateUtil(new Guid("B0720295-9541-40B3-9994-610066224DB8"));5             bool isInitOrder = NHibernate.NHibernateUtil.IsInitialized(customer.Orders);6         }

查看生成的sql语句

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

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

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

一对多关系Lazy加载

多对多关系Lazy加载

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

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

总结

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

(2)在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象白白浪费了许多内存空间。
为了解决以上问题,Hibernate提供了其他两种检索策略:延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象,迫切左外连接检索策略则充分利用了SQL的外连接查询功能,能够减少select语句的数 

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

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

转载地址:https://blog.csdn.net/weixin_34008933/article/details/93244031 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:[Nhibernate]一级缓存
下一篇:如何在Webstorm/Phpstorm中设置连接FTP,并快速进行文件比较,上传下载,同步等操作...

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年03月31日 02时07分50秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章