天天看點

[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