兩種極端情況的案例 N 1次查詢和笛卡爾積

2021-08-25 04:34:49 字數 1484 閱讀 1870

前一篇文章

兩種極端:頻繁的查詢和巨大的結果集

講到了hibernate載入資料時可能會出現的兩種極端情況:頻繁的查詢和一次查出巨大的結果集。其中:n+1次查詢是前一種情況的乙個典型案例,笛卡爾積則是後一種情況的典型案例。下面分別簡單地再總結一下這兩種極端案例出現的原因以及調優方法。

一.n+1次查詢

如果乙個集合是lazy loading的,那麼在第一次訪問到這個集合時,hibernate會生成乙個select被這個集合載入出來。這是n+1中的1。緊接著,

在迭代這個集合的過程中,如果要訪問集合元素所依賴的其他關聯物件時,若它的關聯物件也是lazy loading的,那麼hibernate會生成乙個select從資料庫中載入出這個關聯物件。這樣,n次迴圈就會生成n個select,這就是n+1中的n.

解決n+1次查詢需要在制定動態抓取策略時eager fetch出集合和集合元素的依賴物件,這樣只會生成一條sql。具體做法是在hol中,使用fetch關鍵字來抓取所需要的物件。在criteria中使用setfetchmode方法設定目標抓取物件。具體示例請參考jpwh-13.5.2

二.笛卡爾積

n+1次查詢的反面就是笛卡爾積。一般來說,通過定製動態抓取策略,不會載入出我們不需要的資料,但是有一種情況下,即使我們只載入必需物件也會造成大量資料被select出來,這就是抓取「平行」集合導致的笛卡爾積。

例如:乙個forum有乙個moderator集合,大小為3和乙個thread集合,大小為100。如果在載入forum時,單獨抓取moderator集合,結果集是3,單獨抓取thread集合,結果集是100,同時抓取這兩個集合的結果集是兩個集合的加乘(也就是笛卡爾積)為:3*100.如果還有第三個集合,大小是50的話,那結果集就會變成3*100*50.因此我們可以看到:抓取「平行」集合會產生笛卡爾積,如果集合很多或集合中的元素很多,會使結果集急劇的膨脹。乙個巨大的結果集所帶來的效能損失是什麼呢?想想資料庫伺服器處理這個條資料所花的時間,占用的伺服器的記憶體,通過網路傳輸這些資料,以即到了應用伺服器占用的記憶體和hibernate封裝這些資料所花費的時間,和這些開銷相比,分成兩三個sql(會成數量級的減小結果集)來獲取資料要快得多得多。

hibernate並不禁止我們產生笛卡爾積,也就是說,你可以在乙個抓取計畫中抓取多個「平行」集合。但是有乙個例外,就是bag集合。hibernate不允許同時抓取兩個以上的bag集合。這是因為:the resultset of a product can』t be converted into bag collections, because hibernate can』t know which rows contain duplicates that are valid (bags allow duplicates) and which aren』t.

對於「平行」集合的問題,在抓取時要靈活應對,如果預計到結果集會很大,那麼就不要使用join fetch,而要使用subselect fetch!subselect fetch是平行集合的推薦優化方案。

關於n+1次查詢和笛卡爾積,請參考jpwh_13.2.5節。

SQL中的n 1次select語句查詢問題

如果當sql 資料庫中select語句數目過多,就會影響資料庫的效能,如果需要查詢n個customer物件,那麼必須執行n 1次select查詢語句,下文就將為您講解這個n 1次select查詢問題。在session的快取中存放的是相互關聯的物件圖。預設情況下,當hibernate從資料庫中載入cu...

1 X 1 Y 1 N!的兩種O n 做法

題目大意 求1 x 1 y 1 n!的答案對數。解題思路1 設 m n 由等式知x,y必定大於n 所以再設 x n k m k 帶入 1 m 1 x 1 y 中化簡得到y m m k m,因y為整數,所以要求k整除m m,即k為m m的因子,問題便轉化為求n n 的因子個數,設n p1 e1 p2 ...

equal和 兩種情況下的使用

1 對於字串變數來說,equal比較bai的兩邊物件的內容,所du以內容相同返回的是true。至於你zhi沒問到的 比較的是記憶體中的首位址,所以如果不是同乙個物件,不會返回true 而是false。舉個簡單的例子,string s1 abc s2 abc string s3 new string ...