Railskonferenz

NH-Hotel, Frankfurt am Main

Railskonferenz

NH-Hotel, Frankfurt am Main

Railskonferenz

NH-Hotel, Frankfurt am Main

Andreas Gungl: Batch-Verarbeitung mit ActiveRecord

Im Enterprise-Umfeld hat man neben einem Webfrontend für ein System oft auch Bedarf an Batchverarbeitungen, um im Hintergrund die Inhalte der Datenbank zu überarbeiten.

Selbstverständlich möchte man die Rails-konform in den Model-Klassen untergebrachte Anwendungslogik nicht doppeln (z.B. als StoredProcedure). Doch gerade dann ergibt sich bei größeren Datenmengen oft das Problem, daß ActiveRecord keine cursor-orientierte Verarbeitung bietet und stets das komplette ResultSet in den Speicher laden will.

Es existieren für dieses Problem bereits verschiedene Lösungen (z.B. über Bildung von ID-Gruppen oder Aufteilung per LIMIT / OFFSET), die aber alle nicht sicherstellen, daß die Verarbeitung wirklich innerhalb einer Transaktion mit minimalem Speicherbedarf erfolgen kann.

Im Rahmen einer Inhouse-Anwendung auf Oracle-Basis entstand die Idee, das vorhandene Know-How im Datenbank-Bereich zu nutzen und das ActiveRecord-Frame um eine echte Iterator-Funktion zu erweitern.

Sie sollte so funktionieren, daß man die ActiveRecord#find(_by_sql) Methode um einen Block erweitert, der die Verarbeitung für jedes Objekt der Ergebnismenge übernimmt, wobei auch immer nur dieses eine Objekt im Hauptspeicher gehalten wird:

MyTable.find_each(:conditions => …) do |record|
# do something with record
end

MyTable.find_each_by_sql(…) do |record|
# do something with record
end

Die Implementierung erfordert Erweiterungen an den Datenbank-Adaptern. Sie erfolgte zunächst für Oracle und MySQL. Auch mit JRuby und dem JDBC-Adapter kann die Iteration umgesetzt werden, benötigt da aber Patches für den Java-Part des Datenbank-Adapters (für <= 0.9.0 und 0.9.1 vorhanden).

Bisher bestand kein Bedarf für die Anpassung weiterer Adapter. Dies wäre aber sicherlich mit geringem Aufwand möglich. Probleme ergeben sich bei der unbedachten Nutzung der :include Option von ActiveRecord#find mit 1:n Relationen. N:1 Relationen können dagegen problemlos verarbeitet werden.

2009_batch_mit_active_record.pdf

Foto Andreas Gungl

- geb. 1967 in Dresden
– 1988-1994 Informatik-Studium an der TU Dresden
– 1994-1999 beschäftigt als Softwareentwickler und Berater für kaufm. und Finanz-Software bei Consulting Härtelt GmbH, Reicherberg b. Dresden
– seit 1999 beschäftigt als Softwareentwickler bei der OTTO Software GmbH in
Dresden
– Schwerpunkte der Arbeit sind Design und Optimierung von Logistiksystemen
– seit drei Jahren Nutzung von Ruby und Rails