Ich habe ein System und ein Berichtsmodell. System hat viele Berichte und Bericht gehört zum System. Jeder Tagesbericht besteht aus 175 Datensätzen pro System.Abfrageoptimierung für Indexseite
Ich brauche eine Abfrage auf meiner System-Indexseite, die alle Systeme auflisten sollte, die bei der letzten Berichterstellung gefiltert wurden. Dies war mein erster Versuch.
@systems = System.joins('LEFT JOIN reports ON reports.system_id = systems.id').group('systems.id').order('MAX(reports.created_at) ASC')
Hier werden Systeme mit einem Bericht (System Load (2.1ms)), sondern durch system_id nicht durch Bericht created_at sortiert.
Zweiter Versuch
@systems = System.joins(:reports).where("reports.created_at = (SELECT MAX(created_at) FROM reports p group by system_id having p.system_id = reports.system_id)").order('reports.created_at DESC')
Diese Abfrage macht den Job, aber es ist wirklich langsam (System Load (546.2ms)), trotz eines Index auf report.created_at haben.
Dritter Versuch
@systems = System.joins(:reports).where("reports.id = (SELECT MAX(id) FROM reports p group by system_id having p.system_id = reports.system_id)").order('reports.id DESC')
Auch die Arbeit macht, etwas schneller als der zweite Versuch (System Load (468.3ms)), aber immer noch nicht schnell genug.
Irgendwelche Tipps?
EDIT 03032017
ich die Zahlen auf einem kleinen Test-Datensatz
alte Abfrage
SELECT s.* FROM systems s
JOIN reports r ON r.system_id = s.id
WHERE r.created_at = (
SELECT MAX(created_at)
FROM reports p
group by p.system_id
having p.system_id = r.system_id)
ORDER BY r.id DESC
Time: 622.683 ms
Philip Couling Lösung (sauber, kehrt nur Systeme mit Berichten) hat
SELECT systems.*
FROM systems
JOIN (
SELECT reports.system_id
, MAX(reports.created_at) created
FROM reports
GROUP BY reports.system_id
) AS r_date ON systems.id = r_date.system_id
ORDER BY r_date.created;
Time: 1.434 ms
BookofGr zB Lösung (gibt mir alle Systeme, Bericht oder keinen Bericht)
select systems.* from systems order by updated_at;
Time: 0.253 ms
Ich konnte systemjacks Lösung nicht zum Funktionieren bringen.
schnellste Lösung: bookofgreg
sauberste Lösung: philip couling
Vielen Dank für Ihre Eingabe.
Wirklich glücklich mit dieser Antwort, danke für die Erklärung. Werde es morgen ausprobieren. –