2017-05-03 46 views
0

在性能和邏輯方面,Rails的Active Record查詢中「排序」「過濾器」(Desc或Asc)的位置是否重要?可交換性和活動記錄範圍的順序

例如是1的SAM以下範圍作爲範圍2

SCOPE 1

scope :default_stream, -> { order(deal_end_date: :asc) } # this is the "sorting query" 
scope :scope_1, 
     lambda { default_stream.where('deal_start_date <= ? AND deal_end_date >= ?', Time.zone.now, Time.zone.now).where(is_cool: true) } 

SCOPE 2

scope :scope_2, 
     lambda { Deal.all.where('deal_start_date <= ? AND deal_end_date >= ?', Time.zone.now, Time.zone.now).where(is_cool: true).order(deal_end_date: :asc) } 

我應該先用「排序查詢「那麼其他過濾器(scope1)還是相反(scope2)?

不知道是否有衝擊,但讓我說,交易的數量是非常重要的(> 100000)

回答

1

沒關係。直到您嘗試閱讀結果時,您的範圍才被實際評估。 orderwhere子句可以以任意順序附加到關係中,因爲它們被放置在最終SQL查詢中的相同位置。

如有疑問,請嘗試兩種方法,並在您的示波器上調用.to_sql。您會發現scope1.to_sqlscope2.to_sql完全相同。

給出一個簡單的模型Post,你會發現,Post.order(:name).where(active: true)Post.where(active: true).order(:name)產品相同 SQL:

select * from posts where active = true order by name 

無論是orderwhere發生的 「第一」,這是不可能的。只有一個SQL查詢生成,並且它的所有各種子句(where,order,limit,offset等)到達需要生成語法上有效查詢的位置。

+0

所以先把非排序查詢(其中('deal _..... Time.zone.now).where(is_cool:true))不會更快?我認爲,因爲它會輸出有限/更少的行數,所以排序查詢(order(deal_end_date::asc))作爲第二步將比排序整個數據庫行更快...你說的實際上是(bar)'和'.where(foo).order(bar)的結果,它是通過活動記錄自動爲此優化的? – Mathieu

+0

@Mathieu這根本不是那種工作方式。 ''會做**完全相同的事情**,它們將產生*相同* SQL和*相同*記錄。排序/過濾由數據庫完成,而不是由Ruby完成。'order'或'where'發生「第一次」; Rails將它們全部(不管你以什麼樣的順序調用它們)並將它們變成**一個** SQL查詢 – meagar

+0

好吧,我明白了,將會檢查.to_sql的疑問:)。非常感謝我指出了正確的方向 – Mathieu