2010-02-17 16 views
5

मैं एक रेक उपयोगिता बनाने की कोशिश कर रहा हूं जो हर बार मेरे डेटाबेस को अपडेट करेगा।कुशल थोक अद्यतन रेल डेटाबेस

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 

समस्या मैं आ रही है इस 100 हजार जोड़ प्रविष्टियों में प्रवेश करने के कुछ ही मिनट लगते है जो:

इस कोड को मैं अब तक है। मैं अपना डेटाबेस अपडेट करने का एक और अधिक प्रभावी तरीका खोजना चाहता हूं। आदर्श रूप से यह डेटाबेस प्रकार से स्वतंत्र रहेगा, लेकिन यदि मेरा उत्पादन सर्वर MySQL पर नहीं चल रहा है।

किसी भी अंतर्दृष्टि के लिए धन्यवाद।

उत्तर

9

क्या आपने थोक आयात के लिए AR Extensions का उपयोग करने का प्रयास किया है? जब आप 1000 की पंक्तियों को डीबी में डाल रहे हों तो आपको प्रभावशाली प्रदर्शन सुधार मिलते हैं। अधिक जानकारी के लिए उनके website पर जाएं।

अधिक जानकारी के लिए इन उदाहरणों को देखें

Usage Example 1

Usage Example 2

Usage Example 3

+0

यह वही है जो मैं ढूंढ रहा था, धन्यवाद। – codr

+0

मणि सीएसवी से आयात का समर्थन करता है। यह 'ActiveRecord' त्वरण और सत्यापन लागत को समाप्त करता है। अधिक जानकारी के लिए इस आलेख का संदर्भ लें। http://www.rubyinside.com/advent2006/17-extendingar.html –

+0

भी मेरी मदद की - धन्यवाद! – ambertch

1

आप सभी आवेषण आप की जरूरत के साथ एक पाठ फ़ाइल और उत्पन्न कर सकता है तो अमल उच्च गति ल्यूक के लिए!

दुर्भाग्यवश, वे डीबी विशिष्ट हैं। लेकिन वे कर रहे हैं तेजी mysql के लिए, देखें http://dev.mysql.com/doc/refman/5.1/en/load-data.html

+0

रेल स्वयं SQL सम्मिलन कथन का उपयोग करता है। - अपने रेल लॉग देखें। तो यह विधि एक गति सुधार नहीं होगा। –

+2

बेशक रेल्स इंसर्ट करता है, यह डेटाबेस में रिकॉर्ड कैसे जोड़ता है? लेकिन अपने मूल पोस्ट लेखक में "सेव" विधि का उपयोग कर रहा है जिसमें केवल एक साधारण डालने की तुलना में अधिक ओवरहेड है। मुझे यकीन है कि इसमें प्रत्येक सम्मिलन पर प्रतिबद्धता करना, मॉडल सत्यापन करना आदि शामिल हैं – Zepplock

3

उपयोग डेटाबेस स्तर उपयोगिताओं

mysql -u user -p db_name < mytextfile.txt 

सुनिश्चित नहीं हैं कि अगर यह किसी भी तेजी से लेकिन एक कोशिश के लायक हो जाएगा ...:

0

लैरी, कहते हैं आपके डीबी विशेष आयात उपयोगिताओं का उपयोग करता है, तो इच्छित फ़ाइल फ़ॉर्मेट में आता है। हालांकि, यदि आपको डालने से पहले डेटा में हेरफेर करने की आवश्यकता है, तो आप कई पंक्तियों के लिए डेटा के साथ एक एकल INSERT क्वेरी उत्पन्न कर सकते हैं, जो प्रत्येक पंक्ति के लिए एक अलग क्वेरी का उपयोग करने से तेज़ है (जैसा कि ActiveRecord करेगा)। उदाहरण के लिए:

INSERT INTO iptocs (ip_from, ip_to, country_code) VALUES 
    ('xxx', 'xxx', 'xxx'), 
    ('yyy', 'yyy', 'yyy'), 
    ...; 
संबंधित मुद्दे