I have the following Ruby code that's designed to update item, price and stock data for items in a MSSQL database. It's running on a Ruby 1.8.6/Rails 1.2.3 installation, in its own controller (for now)
What I'm looking for is ways to optimize performance.
Right now each item takes about 0,2 seconds (200ms) to process. Edit: There may be 10,000+ items in the XML file, and 10,000,000+ items in the "Items" and "Price" SQL tables.
I've been told that
composing my own SQL queries directly instead of using the models will be faster, since I'm doing quite a few lookups, how much performance would that lend me?
and selecting many rows at once, doing processing, and inserting at once should be faster, instead of doing it one by one. (How would this be done in practice?)
# counters for statistics
count = 0
skips = 0
# load + parse XML
file = File.read(XML_PATH)
doc = REXML::Document.new file
# loop through products in XML file
doc.elements.each('products') { |product|
itemid = product.attributes['id'].to_i
itemprice = product.elements['price'].text.to_i
item = Item.find_by_id(itemid)
if item.nil?
skips += 1
next
end
# update prices
price = Price.find(:first, :conditions => { :item_id => itemid })
# create new price if price not found
if price.nil?
price = Price.new
price.item_id = itemid
end
price.price = product.elements['price'].text.to_i
price.save
# find + update item stock data
product.elements.each('stocks/location') { |location|
item_stock_location_id = location.attributes['location_code']
item_stock_location = ItemStockLocationCount.find(:first,
:conditions => {
:item_stock_location_id => item_stock_location_id,
:item_id => itemid.to_s
})
if item_stock_location.nil?
item_stock_location = ItemStockLocationCount.new
item_stock_location.item_stock_location_id = item_stock_location_id
item_stock_location.item_id = itemid
end
item_stock_location.stock_qty = location.elements['stock'].text.to_i
item_stock_location.save
}
# update onsite_stock + offsite_stock
item_stock_count_on_site = 0
item_stock_count_off_site = 0
item_stock_loc_qtys = ItemStockLocationQuantity.find_all({ :item_id => itemid.to_s })
item_stock_loc_qtys.each { |stock_loc_qty|
item_stock_count_on_site += stock_loc_qty.stock_qty
item_stock_count_off_site += stock_loc_qty.stock_qty unless stock_loc_qty.item_stock_location_id == 1
}
item.onsite_stock = item_stock_count_on_site
item.offsite_stock = item_stock_count_off_site
# update price lock
item.price_lock = product.elements['price_locked']
if item.price_lock == 1
item.vat_price = product.elements['price']
item.price = (itemprice - ((itemprice * 25)/ (100 + 25)))
end
item.save
count += 1
# progress bar
if count%100 == 0
printf '.'
end
}
puts 'Item Count: ' + count.to_s
puts 'Items skipped: ' + skips.to_s