2016-12-21 64 views
0

我對ActiveRecord比較陌生,我與Sinatra一起使用。目前,我正在建設小型網站。我沒有遇到任何查詢花費太長時間的問題,但我想知道如何最佳地優化搜索,所以我的網站是可擴展的。如何編寫高效的活動記錄查詢

這是我一直想知道的。 ActiveRecord是否將一個查詢分解爲多個不同於一個函數的函數?

# Single 
BlogPost.last(5) 

# Broken Down 
BlogPost.all.limit(5) 

這更像是一個概念性問題:ActiveRecord如何運行搜索?添加更多功能會使搜索效率降低嗎?當查詢分解爲多個函數BlogPost.where(publish: true) - 假設where(publish: true)返回五十個結果,而limit將其限制爲五個。它是否首先找到所有五十個publish: true,然後在五點之後切斷所有內容,還是足夠聰明以在找到前五個之後停止搜索?

回答

2

你的預感是正確的。鏈接ActiveRecord查詢是一個好習慣。

假設您的BlogPost表格有一百萬行。

然後說BlogPost.all會很慢,但要說BlogPost.all.limit(1)會很快。

alllimit都是ActiveRecord的一部分。返回值響應數組方法,但不是數組。這有一些例外。例如,返回模型實例,但您可以將它們作爲鏈中的最後一個查詢方法。 pluck返回一個普通的紅寶石數組。

BlogPost.all[1]會和BlogPost.all一樣慢,因爲[ ]是一個數組方法,而不是ActiveRecord。

當您將ActiveRecord方法鏈接在一起時,只有在將方法轉換爲數組或嘗試讀取某些數據之後纔會執行查詢。

因此query = BlogPost.all.order(id: :desc).reorder(id: :asc).limit(1)還沒有實際加載數據庫中的任何數據。也讀入preloading data)哪些可以解決緩慢的N+1查詢。

如果您接着說query.to_a,query.reduce等等,然後Arel(什麼ActiveRecord是建立在),完成查詢並執行它。

您可以撥打<query>.to_sql看到下面的查詢:

class Foo < ActiveRecord::Base 
end 

Foo.all.to_sql 
#=> "SELECT \"foos\".* FROM \"foos\"" 
Foo.all.limit(1).to_sql 
#=> "SELECT \"foos\".* FROM \"foos\" LIMIT 1"