2017-07-04 1 views
1

ich eine Aktion mit dieser Art von Code haben:Lange Differenz zwischen Serverantwort und Browser-Ergebnis mit umfasst

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

Der Server Antwort gibt:

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 

Aber im Browser, die Rendering Nimm 6 Sekunden (für eine leere Seite). Es gibt einen Unterschied von 4 Sekunden und es erhöht sich, wenn ich 2000 für einen höheren Wert ändere.

Es ist korrekt, wenn ich die includes oder die to_a entfernen. Es ist das gleiche, wenn ich das tue:

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

Das Entfernen der Includes ist am schnellsten, auch wenn es ein n + 1 Abfrageproblem gibt.

Ich benutze Ruby 2.3 und Rails 4.2.

Ich nehme an, es gibt ein Problem mit der Speicherzuweisung, aber ich weiß nicht, wie ich es lösen soll. Was kann ich tun?

Antwort

0

Warum verwenden Sie Includes? Wie sieht das SQL aus? Vielleicht sehen Sie, wenn Sie die SQL lesen:

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

Die Kosten für die Abfrage können sehr groß sein, wenn Sie viel ist haben der Zeilen!

Auch weil Ihr Ergebnis kann groß sein. Es kostet Geld, riesige Arrays in Ruby zu manipulieren.

versuchen, so viel wie möglich aktive Datensatz Methoden auf Ihren Daten zu verwenden, bevor Rubin verwendet wird, auch zum Beispiel:

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) 

Auch das Protokoll überprüfen, wenn Sie Seite zugegriffen wird, um zu sehen, wenn Sie N nicht haben +1. Das Juwel bullet kann Ihnen auch helfen. Wenn es dir nicht hilft. Verwenden Sie rack-mini-profiler.

Weiterführende Literatur:

0

Vergewissern Sie sich, dass Sie die Beziehungen indiziert sind. Darüber hinaus verwenden Sie jedes Mal zupfen.

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

Wenn die Indizes in Ordnung sind, überprüfen Sie bitte, ob alle Daten für Sie notwendig sind. Wenn alles, was Sie von Ihrer Beziehung brauchen, nur eine ID ist, können Sie Joins verwenden und nur die ID auswählen.

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') 
Verwandte Themen