我正在尝试构建一个rake实用程序,它会经常更新我的数据库。
这是我到目前为止的代码:
namespace :utils do
# utils:update_ip
# Downloads the file frim <url> to the temp folder then unzips it in <file_path>
# Then updates the database.
desc "Update ip-to-country database"
task :update_ip => :environment do
require 'open-uri'
require 'zip/zipfilesystem'
require 'csv'
file_name = "ip-to-country.csv"
file_path = "#{RAILS_ROOT}/db/" + file_name
url = 'http://ip-to-country.webhosting.info/downloads/ip-to-country.csv.zip'
#check last time we updated the database.
mod_time = ''
mod_time = File.new(file_path).mtime.httpdate if File.exists? file_path
begin
puts 'Downloading update...'
#send conditional GET to server
zipped_file = open(url, {'If-Modified-Since' => mod_time})
rescue OpenURI::HTTPError => the_error
if the_error.io.status[0] == '304'
puts 'Nothing to update.'
else
puts 'HTTPError: ' + the_error.message
end
else # file was downloaded without error.
Rails.logger.info 'ip-to-coutry: Remote database was last updated: ' + zipped_file.meta['last-modified']
delay = Time.now - zipped_file.last_modified
Rails.logger.info "ip-to-country: Database was outdated for: #{delay} seconds (#{delay / 60 / 60 / 24 } days)"
puts 'Unzipping...'
File.delete(file_path) if File.exists? file_path
Zip::ZipFile.open(zipped_file.path) do |zipfile|
zipfile.extract(file_name, file_path)
end
Iptocs.delete_all
puts "Importing new database..."
# TODO: way, way too heavy find a better solution.
CSV.open(file_path, 'r') do |row|
ip = Iptocs.new( :ip_from => row.shift,
:ip_to => row.shift,
:country_code2 => row.shift,
:country_code3 => row.shift,
:country_name => row.shift)
ip.save
end #CSV
puts "Complete."
end #begin-resuce
end #task
end #namespace
我遇到的问题是,这需要几分钟才能输入10万多个条目。我想找到一种更有效的方式来更新我的数据库。理想情况下,这将保持独立于数据库类型,但如果不是,我的生产服务器将在MySQL上运行。
感谢您的任何见解。
答案 0 :(得分:9)
您是否尝试使用AR Extensions进行批量导入?当您向数据库插入1000行时,您将获得令人印象深刻的性能改进。访问他们的website了解更多详情。
有关详细信息,请参阅这些示例
答案 1 :(得分:3)
将数据库级实用程序用于高速Luke!
不幸的是,它们是特定于数据库的。但他们快 对于mysql,请参阅http://dev.mysql.com/doc/refman/5.1/en/load-data.html
答案 2 :(得分:1)
您可以生成包含所需INSERT的文本文件,然后执行:
mysql -u user -p db_name < mytextfile.txt
不确定这是否会更快但值得一试......
答案 3 :(得分:1)
我目前正在尝试使用activerecord-import,这听起来非常有希望:
答案 4 :(得分:0)
正如Larry所说,如果文件采用您想要的格式,请使用特定于数据库的导入实用程序。但是,如果您需要在插入之前操作数据,则可以生成包含多行数据的单个INSERT查询,这比为每行使用单独的查询要快(如ActiveRecord所做的那样)。例如:
INSERT INTO iptocs (ip_from, ip_to, country_code) VALUES
('xxx', 'xxx', 'xxx'),
('yyy', 'yyy', 'yyy'),
...;