简体   繁体   中英

Rake task too slow

I have a rake task which accumulate all info from several tables into one, each table is about 200 000 rows:

task :migrate_all_info_tables_to_one => :environment do
    profiles = Profile.all
    profiles.each do |profile|
      basic_info_items = profile.basic_info_items
      basic_info_items.each do |item|
        info = InfoItem.find_or_initialize_by_kind_and_value_and_link_and_description(:kind => 'info', :value => item.parameter, :link => item.link != 'none' ? item.link : nil, :description => item.value)
        profile.info_items << info
      end

      cities = profile.cities
      cities.each do |city|
        city = InfoItem.find_or_initialize_by_kind_and_value_and_link_and_description(:kind => 'city', :value => city.title, :link => city.link != 'none' ? city.link : nil, :description => city.description)
        profile.info_items << city
      end

      histories = profile.histories
      histories.each do |item|
        info = InfoItem.find_or_initialize_by_kind_and_value_and_link_and_description(:kind => 'history', :value => item.year, :link => item.link != 'none' ? item.link : nil, :description => item.event)
        profile.info_items << info
      end

      contacts = profile.contacts
      contacts.each do |item|
        info = InfoItem.find_or_initialize_by_kind_and_value_and_link_and_description(:kind => 'contact', :value => item.parameter, :link => item.link != 'none' ? item.link : nil, :description => item.value)
        profile.info_items << info
      end
    end
  end

I added all necessary indexes in tables (using mysql 5.1.6), form mysql each separate query take 0.00 sec, from ruby console too. But when I run this rake task it processing only 100 profiles records per minute, why or maybe I am doing smth wrong?

PS: I do this because I made ​​a mistake in my project database architecture.

To make it more efficient you can eager load the profile relations you use in the script, use :

Profile.includes(:basic_info_items, :cities, :histories, :contacts).all

instead of Profile.all .

You may also want to use Profile.find_each instead of Profile.all to avoid loading all the profile in memory.

If you have related records on Profile, and are accessing them as you loop over all the profiles, ActiveRecord might be doing a separate select for each one, complete with BEGIN and COMMIT. This will slow things down even if each select is very fast.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Have a look at the section on eager loading associations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM