Internetbureau Holder

ActiveRecord is nice, maar soms is raw SQL beter

Chris Brandhorst wo 10 feb 10

Met ActiveRecord heb je als Rails-ontwikkelaar een hoop nuttige methoden in handen om het werken met modellen en het aanpassen van een database te vergemakkelijken.

Het is echter niet altijd de snelste manier… AR voegt uiteraard een hoop overhead toe dat niet nodig is bij het uitvoeren van basale taken op de database, zoals in migrations.

Zo hadden wij een Customers-tabel met daarin een telefoonnummer en een mobiel telefoonnummer. Dit moest er 1 worden, en de mobiele telefoon had prevalentie. Dus wat doe je dan: je maakt een backup-kolom van de mobiele telefoon info, kopieert het originele mobiele nummer naar deze kolom en zet daarna het mobiele nummer gelijk aan het telefoonnummer als er geen mobiel nummer was. In de AR-based migration staat dan het volgende:

add_column :customers, :mobile_number_old, :string, :length => 50
Customer.reset_column_information
Customer.all.each do |c|
  c.mobile_number_old = c.mobile_number
  c.mobile_number = c.phone_number if c.mobile_number.nil? || c.mobile_number.strip.blank?
  c.save
end

Ziet er goed uit. Echter, op de tabel met 33.100 records was de migration na 10 minuten nog niet klaar.

Een andere aanpak was nodig, dus werd gewoon raw SQL geprobeerd:

add_column :customers, :mobile_number_old, :string, :length => 50
execute "UPDATE customers SET mobile_number_old = mobile_number"
execute "UPDATE customers SET mobile_number = phone_number WHERE mobile_number IS NULL OR TRIM(mobile_number) = ''"

Deze query was na 3 seconden klaar.

Probeer dus goed te bedenken of je een operatie op grote aantallen records niet beter met raw SQL kan doen!

Gepost in hor |  3 reacties

Chris Brandhorst wo 10 feb 10 16:47

Jan, bedankt voor de aanvulling!

Jouw methode ziet er inderdaad wat eleganter uit, maar brengt natuurlijk wel weer iets aan overhead mee. Hoeveel dat exact is, zal geprobeerd moeten worden, maar het is te verwachten dat deze opzet niet veel zal schelen in vergelijking met de execute uitroep.

Arie Meeldijk wo 10 feb 10 11:15

Jan de Poorter heeft gelijk. Bij de AR-based migration van de blogpost worden alle records ingelezen en tot AR-objecten gesmeed. Deze worden vervolgens 1 voor 1 geupdate, niet heel raar dat dit dus lang duurt :)

Anton Astashov wo 10 feb 10 09:54

ActiveRecord heeft hier een speciale methode voor, ActiveRecord::Base#update_all

Volgens mij nog steeds eleganter

Customer.update_all(‘mobile_number_old = mobile_number’)
Customer.update_all(‘mobile_number = phone_number’, ’mobile_number IS NULL OR TRIM = "")

Plaats je reactie





Welcome to Holland On Rails

This weblog is the official Ruby techblog from the guys at Holder, a Ruby development company. Holder is also the company behind the RubyAndRails Europe Conference in Amsterdam.

Recente Jobs


Bekijk alle jobs »»

Gereedschapskist

Onmisbare tools voor
iedere developer!
Ruby On Rails
Framework voor de web 2.0 developer. Eindelijk vooruitgang!
TextMate
Editor for true pro's
Typ, tab, top :-)
Nee, niet voor Win.
Made On A Mac
En nou is het over met die saaie grijze Windows bak van je!

Auteurs op deze site

Chris Obdam

'Less is more' evangelist, past dit ook dagelijks toe op zijn tandenborstel.

Chiel Wester

Snelheidswonder op Ruby wielen. Leuk om mee te pair-programmen ;-) Recommend Me

Stephan Kaag

Het eerste Rails coreteam- member uit Nederland? Rails evangelist van het eerste uur.

Paul Engel

Én Rails programmeren én interfaces designen? Je zou hem superman kunnen noemen..

Dax Huiberts

Official Zip-Programmer, skinny code is helemaal zijn ding. Haalt meer code weg dan dat er bij komt.

Freek Monteban

Het nieuwste telg uit het Holland on Rails nest! Hij doet niets anders meer!

Johan Vermeulen

De stylesheet-koning uit de kop van Noord-Holland!