關于Rails中N+1查詢的簡單理解

  • 什么是N+1問題
    舉個例子,我們數(shù)據(jù)庫中有兩張表蠕蚜,一個是Users尚洽,一個是BlogsBlogs中含有一個外鍵user_id靶累,指向了Users的主鍵id腺毫。
    想要得到所有User以及其分別對應的Blog,一種寫法是
SELECT * FROM Users; 
SELECT * FROM Users WHERE Blogs.user_id = #{user.id}

這樣我們實際對數(shù)據(jù)庫做了N+1次查詢:選擇所有User一次得到N個User挣柬,對于N個User分別選擇其對應的Blog一共N次潮酒。所以,一共執(zhí)行了N+1次查詢邪蛔,這就是N+1問題急黎。

  • Rails中的N+1問題
    兩個model:user、blog侧到,其中
has_many :blogs
belongs_to :user

想要獲得所有user的所有blogs時叁熔,使用:

users = User.all
users.each {|user| puts user.blogs}

輸出是

User Load (0.6ms)  SELECT `users`.* FROM `users`

  Blog Load (0.3ms)  SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`user_id` = 2  ORDER BY `blogs`.`created_at` DESC
#<Blog:0x00000005b0cfe8>
#<Blog:0x00000005b0ce58>
#<Blog:0x00000005b0cd18>
#<Blog:0x00000005b0cbb0>
#<Blog:0x00000005b0ca70>
#<Blog:0x00000005b0c930>
#<Blog:0x00000005b0c7f0>
#<Blog:0x00000005b0c6b0>
#<Blog:0x00000005b0c570>
#<Blog:0x00000005b0c430>
#<Blog:0x00000005b0c2f0>
 Blog Load (0.2ms)  SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`user_id` = 5  ORDER BY `blogs`.`created_at` DESC
#<Blog:0x00000005ae2c98>
#<Blog:0x00000005ae2b58>
#<Blog:0x00000005ae2a18>
#<Blog:0x00000005ae28b0>
#<Blog:0x00000005ae26f8>
#<Blog:0x00000005ae25b8>
#<Blog:0x00000005ae2450>
#<Blog:0x00000005ae2310>
#<Blog:0x00000005ae2108>
#<Blog:0x00000005ae1f00>
 Blog Load (0.4ms)  SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`user_id` = 20  ORDER BY `blogs`.`created_at` DESC
 Blog Load (0.2ms)  SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`user_id` = 21  ORDER BY `blogs`.`created_at` DESC

上面就造成了N+1的查詢問題。每遇到一個user,就會去執(zhí)行一次SELECTblogs.* FROMblogsWHEREblogs.user_id= 5 ORDER BYblogs.created_atDESC的查詢語句床牧。如果user很多荣回,就容易造成性能問題。

  • 如何解決
    rails推薦的解決方法是用Eager Loading Associations
    在查詢user的時候戈咳,使用includes同時把blogs也查詢出來心软。
users = User.all.includes(:blogs)
user.each {|user| puts user.blogs}

輸出:

User Load (0.3ms)  SELECT `users`.* FROM `users`
 Blog Load (0.3ms)  SELECT `blogs`.* FROM `blogs` WHERE `blogs`.`user_id` IN (2, 5, 20, 21)  ORDER BY `blogs`.`created_at` DESC

#<Blog:0x00000003a7c6c0>
#<Blog:0x00000003a7c468>
#<Blog:0x00000003a7a960>
#<Blog:0x00000003a7a2d0>
#<Blog:0x00000003a7a0c8>
#<Blog:0x00000003a79ee8>
#<Blog:0x00000003a799e8>
#<Blog:0x00000003a78f20>
#<Blog:0x00000003a784f8>
#<Blog:0x00000003a77f30>
#<Blog:0x00000003a77cb0>
#<Blog:0x00000003a7ce40>
#<Blog:0x00000003a7cbe8>
#<Blog:0x00000003a7c990>
#<Blog:0x00000003a7c170>
#<Blog:0x00000003a7bec8>
#<Blog:0x00000003a7b860>
#<Blog:0x00000003a7b608>
#<Blog:0x00000003a7b180>
#<Blog:0x00000003a7af78>
#<Blog:0x00000003a7adc0>

我的理解是這樣:在第一次查詢users的時候,通過一條查詢語句把相關的blogs也查詢出來了IN (2,5,20,21)著蛙。這樣删铃,在后面使用users的時候。就不用再去查詢數(shù)據(jù)庫了踏堡。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猎唁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子顷蟆,更是在濱河造成了極大的恐慌诫隅,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帐偎,死亡現(xiàn)場離奇詭異逐纬,居然都是意外死亡,警方通過查閱死者的電腦和手機削樊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門豁生,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兔毒,“玉大人,你說我怎么就攤上這事甸箱∮” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵芍殖,是天一觀的道長豪嗽。 經(jīng)常有香客問我,道長围小,這世上最難降的妖魔是什么昵骤? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任树碱,我火速辦了婚禮肯适,結果婚禮上,老公的妹妹穿的比我還像新娘成榜。我一直安慰自己框舔,他們只是感情好,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布赎婚。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轿亮。 梳的紋絲不亂的頭發(fā)上捐寥,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天,我揣著相機與錄音撩嚼,去河邊找鬼停士。 笑死,一個胖子當著我的面吹牛完丽,可吹牛的內(nèi)容都是我干的恋技。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼逻族,長吁一口氣:“原來是場噩夢啊……” “哼蜻底!你這毒婦竟也來了?” 一聲冷哼從身側響起聘鳞,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤薄辅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后抠璃,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體长搀,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年鸡典,在試婚紗的時候發(fā)現(xiàn)自己被綠了源请。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谁尸,靈堂內(nèi)的尸體忽然破棺而出舅踪,到底是詐尸還是另有隱情,我是刑警寧澤良蛮,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布抽碌,位于F島的核電站,受9級特大地震影響决瞳,放射性物質發(fā)生泄漏货徙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一皮胡、第九天 我趴在偏房一處隱蔽的房頂上張望痴颊。 院中可真熱鬧,春花似錦屡贺、人聲如沸蠢棱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泻仙。三九已至,卻和暖如春量没,著一層夾襖步出監(jiān)牢的瞬間玉转,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工殴蹄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留究抓,地道東北人。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓饶套,卻偏偏與公主長得像漩蟆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妓蛮,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內(nèi)容