2017-07-04 86 views
1

我有這種代碼的作用:長差與包括

Timesheet::WorkPeriod.includes(:ship).limit(2000).to_a 
    render nothing: true 

服務器答案給出:

method=GET path=/timesheet_reports/rest_hours format=html controller=Company::Timesheet::ReportsController action=rest_hours status=200 duration=2106.43 view=3.68 db=23.75 

但是,在瀏覽器中渲染需要6秒(空白)頁面。有4秒的差異,如果我更改2000更高的價值,它會增加。

這是正確的,如果我刪除includesto_a。如果我這樣做也是如此:

Timesheet::WorkPeriod.includes(:ship).limit(2000).each(&:id) 

即使存在n + 1查詢問題,刪除包含也是最快的。

我使用ruby 2.3和Rails 4.2。

我想有一個內存分配問題,但我不知道如何解決它。我能做什麼?

回答

0

爲什麼使用includes? SQL的外觀如何? 也許如果你讀了SQL,你會看到:

Timesheet::WorkPeriod.includes(:ship) 
# SELECT "work_period".* FROM "work_period" 
# SELECT "ship".* FROM "ship" WHERE "ship"."work_period_id" IN (....) 

用於查詢的成本是巨大的,如果你有行很多的!

也因爲你的結果可能很大。它花費巨大的數組在紅寶石中操作。

嘗試使用您的數據儘可能的活動記錄的方法使用Ruby之前,還例如:

Timesheet::WorkPeriod.includes(:ship).limit(2000).each(&:id) 
# use select if you need AR object 
Timesheet::WorkPeriod.includes(:ship).limit(2000).select(:id) 
# or pluck if you need the list of value in column 
Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck(:id) 

另外,檢查日誌,當你訪問頁面看到,如果你不具備N- +1。寶石bullet也可以幫助你。 如果它不能幫助你。使用rack-mini-profiler

延伸閱讀:

0

確保您的關係進行索引。此外,使用pluck而不是每個。

Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck(:id) 
# Depending which ID you need 
Timesheet::WorkPeriod.includes(:ship).limit(2000).pluck('ships.id') 

如果索引很好,請仔細檢查是否所有數據都是您需要的。如果您的關係只需要一個ID,就可以隨意使用連接並僅選擇ID。

Timesheet::WorkPeriod.joins(:ship).limit(2000).pluck('ships.id') 
# You may also want left join 
Timesheet::WorkPeriod 
    .joins('LEFT OUTER JOIN ships ON ships.work_period_id = work_periods.ids') 
    .limit(2000).pluck('ships.id')