2 Stimmen

Die Abfrage ist schnell in MySQL, aber langsam, wenn sie über Rails ActiveRecord ausgeführt wird

Ich habe eine Abfrage, die in der MySQL-Konsole sehr schnell läuft, aber sehr langsam ist, wenn ich sie mit Rails Active Record ausführe. Dies ist die Abfrage, die gegen eine Tabelle mit 7 Millionen Datensätzen läuft:

select broker_id,count(abserror),avg(abserror) from fc_estimates where ( fpe > '2000-05-28') and ( fpe < '2003-06-30') group by broker_id order by broker_id;

Das dauert 3 Minuten.

Dann führe ich diese Abfrage in Rails Active Record aus:

stats = Estimate. select([ "broker_id", "count(abserror) as abserror_count", "avg(abserror) as abserror_avg" ]). where( :fpe => ((fpe-1098).to_date..(fpe+30).to_date)) group("broker_id"). order("broker_id")

die folgendes SQL generiert (Ausgabe von to_sql)

SELECT broker_id, count(abserror) as abserror_count, avg(abserror) as abserror_avg FROM fc_estimates WHERE (fc_estimates.fpe BETWEEN '2000-05-28' AND '2003-06-30') GROUP BY broker_id ORDER BY broker_id

und dauert 1 Stunde und 40 Minuten, um ausgeführt zu werden. Es gibt 250 Datensätze zurück.

Ich benutze Windows 7, MySQL 5.1, Ruby 1.8.7, ActiveRecord 3.04, mysql2 gem 0.2.6

Es handelt sich um InnoDB-Tabellen und ich habe die innodb_buffer_pool_size auf 480M erhöht (was bei anderen Abfragen geholfen hat). Eine Sache, die ich beobachte, ist, dass der MySQL-Speicherverbrauch auf etwa 500M ansteigt und dann eine Menge Festplattenaktivität (Seitenaustausch) stattfindet. Das erklärt etwas.

Aber warum erhalte ich immer noch so schlechte Leistung, wenn die gleiche Abfrage in der MySQL-Konsole nur 3 Minuten dauert? Danke für alle Ideen oder jemanden, der eine ähnliche Situation erlebt hat.

UPDATE 2011-02-24

Ich habe auf MySQL 5.5 aktualisiert. Jetzt läuft meine Abfrage in der Konsole in etwa 1min40sek. Und mit ActiveRecords dauert es etwa 40 Minuten.

1voto

Lucas Punkte 1182

Es läuft viel mehr in Ihrem Ruby-Code als nur eine SQL-Abfrage. Ich bin kein Ruby-Jedi, aber ich kann einige Dinge hervorheben.

Windows ist nicht der beste Ort, um mit dem MRI zu arbeiten. Vielleicht sollten Sie 1.9.2 oder JRuby ausprobieren - oder sogar auf ein anderes *nix-Betriebssystem umsteigen.

(fpe-1098).to_date..(fpe+30).to_date) erstellt eine Bereichsinstanz für die Datumsintervalle. Vielleicht sollten Sie eine andere Syntax ausprobieren, z. B. ['fpe > ? AND fpe < ?'(fpe-1098),(fpe+30)] - damit weniger Objekte erstellt werden.

Da Sie keine Estimate-Instanzen abrufen, anstatt die Abfrage mit der Modelklasse auszuführen, können Sie den generierten SQL-Code an ActiveRecord::Base.connection.execute übergeben. Möglicherweise wird dadurch weniger Arbeitsspeicher benötigt und weniger Objekte erstellt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X