2013-10-29 72 views
0

這可能聽起來有點笨,但我不是數據庫專家。爲什麼我們應該避免1 + N查詢問題?

例如,如果我們有一個User模型和Comment模型,每個評論屬於用戶,也有獲取與他們的用戶一起的所有意見的方式有兩種:

# 1. 
@comments = Comment.all(:include => :user) 

# 2. 
@comments = Comment.all() 
@users = [] 
@comments.each do |comment| # Or we do the same loop in embedded code in the view 
    @users << User.find(comment.user) 
end 

我的問題是,因爲這兩種方法都會獲取所有評論及其用戶數據(這意味着我們從硬盤驅動器和互聯網上讀取並傳輸相同數量的信息),爲什麼第二種方法被認爲是不好的做法?

+5

因爲更多的查詢通常會造成更糟糕的性能,並且執行100次查詢可能會減少到2個毫無意義。 –

+0

@DamienRoche查詢必須使更多查詢的性能變差嗎? – OneZero

+0

我將在一個答案中演示.. –

回答

4

請允許我說明爲什麼:

Message.count 
13228 

Benchmark.measure { Message.all.each(&:user) } 
16s 

Benchmark.measure { Message.all(include: :user).each(&:user) } 
2s 

隨着100行,這是一個更現實的獲取:

Benchmark.measure { Message.limit(100).each(&:user) } 
0.12s 

Benchmark.measure { Message.includes(:user).limit(100).each(&:user) } 
0.01s 

正如你可以看到,圍繞10倍速度更快,更小的壓力在數據庫上。

+0

「消息」。 all.map {|!留言|消息| message.user}' 比較? – Drew

+0

@Drew恐怕這不是有效的語法。你可以重新檢查嗎?無論哪種方式,調用'message.user'不包括仍然會導致13k查詢,而不是2. –

+0

哈哈是啊,我不記得什麼命令合併兩個數組是,但是無論如何,我不知道爲什麼我認爲這會更快!哈哈 – Drew

2

一次又一次敲擊DB以獲取與Comment記錄關聯的User記錄將影響應用程序的性能。

如果評論數量太高,並且您在循環播放以獲取所有關聯用戶,則這會變得更慢。

鑑於Comment.all(:include => :user的情況,只有兩個查詢會一直被觸發。一個獲得評論,一個獲取所有關聯的用戶。

相關問題