2012-08-28 22 views
5

मैं बड़ी मात्रा में सीवी डेटा आयात करना चाहता हूं (सीधे एआर नहीं, लेकिन कुछ fetches के बाद), और मेरा कोड बहुत धीमा है।सीएसवी आयात को तेज करें

def csv_import 
    require 'csv' 
    file = File.open("/#{Rails.public_path}/uploads/shate.csv") 
    csv = CSV.open(file, "r:ISO-8859-15:UTF-8", {:col_sep => ";", :row_sep => :auto, :headers => :first_row}) 

    csv.each do |row| 
     #ename,esupp= row[1].split(/_/) 
     #(ename,esupp,foo) = row[1]..split('_') 
     abrakadabra = row[0].to_s() 
     (ename,esupp) = abrakadabra.split(/_/) 
     eprice = row[6] 
     eqnt = row[1] 
     # logger.info("1) ") 
     # logger.info(ename) 
     # logger.info("---") 
     # logger.info(esupp) 
     #---- 
     #ename = row[4] 
     #eprice = row[7] 
     #eqnt = row[10] 
     #esupp = row[12] 

     if ename.present? && ename.size>3 
     search_condition = "*" + ename.upcase + "*"  

     if esupp.present? 
      #supplier = @suppliers.find{|item| item['SUP_BRAND'] =~ Regexp.new(".*#{esupp}.*") } 
      supplier = Supplier.where("SUP_BRAND like ?", "%#{esupp}%").first 
      logger.warn("!!! *** supp !!!") 
      #logger.warn(supplier) 
     end 

     if supplier.present? 

      @search = ArtLookup.find(:all, :conditions => ['MATCH (ARL_SEARCH_NUMBER) AGAINST(? IN BOOLEAN MODE)', search_condition.gsub(/[^0-9A-Za-z]/, '')]) 
      @articles = Article.find(:all, :conditions => { :ART_ID => @search.map(&:ARL_ART_ID)}) 
      @art_concret = @articles.find_all{|item| item.ART_ARTICLE_NR.gsub(/[^0-9A-Za-z]/, '').include?(ename.gsub(/[^0-9A-Za-z]/, '')) } 

      @aa = @art_concret.find{|item| item['ART_SUP_ID']==supplier.SUP_ID} #| @articles 
      if @aa.present? 
      @art = Article.find_by_ART_ID(@aa) 
      end 

      if @art.present? 
      @art.PRICEM = eprice 
      @art.QUANTITYM = eqnt 
      @art.datetime_of_update = DateTime.now 
      @art.save 
      end 

     end 
     logger.warn("------------------------------")  
     end 

     #logger.warn(esupp) 
    end 
end 

यहां तक ​​कि अगर मैं इसे हटा देता हूं और केवल यह प्राप्त करता हूं, तो यह धीमा है।

def csv_import 
    require 'csv' 
    file = File.open("/#{Rails.public_path}/uploads/shate.csv") 
    csv = CSV.open(file, "r:ISO-8859-15:UTF-8", {:col_sep => ";", :row_sep => :auto, :headers => :first_row}) 

    csv.each do |row| 
    end 
end 

क्या कोई मुझे fastcsv का उपयोग करके गति बढ़ाने में मदद कर सकता है?

+0

इस गति को प्रभावित नहीं करेगा, लेकिन आप को बंद नहीं कर रहे हैं 'उपयोग File.readlines ("/फ़ाइल ") file'। फिर आपको फ़ाइल खोलने के बारे में चिंता करने की ज़रूरत नहीं है। –

+0

@ वे आपको कौन नहीं समझते हैं, विवरण उदाहरण दे सकते हैं? – byCoder

+0

यदि आप File.open चलाते हैं तो आपको फ़ाइल के करीब होना चाहिए। आप खुली फाइलों को रिसाव नहीं करना चाहते हैं। http://stackoverflow.com/questions/4795447/rubys-file-open-and-the-need-for-f-close –

उत्तर

2

के लिए मुझे नहीं लगता कि यह बहुत तेजी से मिल जाएगा है।

यह कहा गया है कि कुछ परीक्षणों से पता चलता है कि ट्रांसकोडिंग (मेरे परीक्षण मामले के लिए लगभग 15%) के लिए समय का एक महत्वपूर्ण हिस्सा खर्च किया जाता है। तो अगर आप इसे छोड़ सकते हैं (उदा। यूटीएफ -8 में सीएसवी बनाकर) आप कुछ सुधार देखेंगे।

इसके अलावा, ruby-doc.org के अनुसार पढ़ने CSV में के लिए "प्राथमिक" इंटरफेस foreach है, इसलिए इस प्राथमिकता दी जानी चाहिए:

def csv_import 
    import 'csv' 
    CSV.foreach("/#{Rails.public_path}/uploads/shate.csv", {:encoding => 'ISO-8859-15:UTF-8', :col_sep => ';', :row_sep => :auto, :headers => :first_row}) do | row | 
    # use row here... 
    end 
end 

अद्यतन

तुम भी कई में पार्स करने विभाजित करने का प्रयास कर सकता है धागे।

N = 10000 
def csv_import 
    all_lines = File.read("/#{Rails.public_path}/uploads/shate.csv").lines 
    # parts will contain the parsed CSV data of the different chunks/slices 
    # threads will contain the threads 
    parts, threads = [], [] 
    # iterate over chunks/slices of N lines of the CSV file 
    all_lines.each_slice(N) do | plines | 
    # add an array object for the current chunk to parts 
    parts << result = [] 
    # create a thread for parsing the current chunk, hand it over the chunk 
    # and the current parts sub-array 
    threads << Thread.new(plines.join, result) do | tsrc, tresult | 
     # parse the chunk 
     parsed = CSV.parse(tsrc, {:encoding => 'ISO-8859-15:UTF-8', :col_sep => ";", :row_sep => :auto}) 
     # add the parsed data to the parts sub-array 
     tresult.replace(parsed.to_a) 
    end 
    end 
    # wait for all threads to finish 
    threads.each(&:join) 
    # merge all the parts sub-arrays into one big array and iterate over it 
    parts.flatten(1).each do | row | 
    # use row (Array) 
    end 
end 

यह 10000 लाइनों के टुकड़ों में इनपुट विभाजन और मात्रा से प्रत्येक के लिए एक पार्स धागा बनाता है: मैं कुछ प्रदर्शन वृद्धि इस कोड के साथ प्रयोग (शीर्षक बाहर छोड़ दिया के उपचार) पर पहुंच गया। प्रत्येक धागे को इसके परिणाम संग्रहीत करने के लिए सरणी parts में उप-सरणी पर सौंप दिया जाता है। जब सभी धागे समाप्त हो जाते हैं (threads.each(&:join) के बाद) parts में सभी हिस्सों के परिणाम संयुक्त होते हैं और यही वह है।

+0

एचएम, क्या आप मेरे प्रश्न में अपने अपडेट accroding को फिर से लिख सकते हैं? ... आप + 50 – byCoder

+0

भी प्राप्त कर सकते हैं, मैं अपने सीएसवी को utf8 में कैसे परिवर्तित कर सकता हूं ताकि रूबी इसे समझ सके? मैं utf8 आज़माता हूं, सब ठीक है, लेकिन जब मेरे utf8-doc में रूसी शब्द दिखाई देता है (इसमें उनमें से कई होंगे) यह utf8 त्रुटि भेजता है ... इसे कैसे हल करें? – byCoder

+0

क्षमा करें, मैं उस प्रश्न को समझ नहीं पा रहा हूं। क्या रूबी को यूटीएफ -8 सीएसवी पढ़ने में कोई समस्या है या सीएसवी एक अलग एन्कोडिंग है? शायद आपको एक और स्टैक ओवरफ्लो प्रश्न पोस्ट करना चाहिए। –

2

यह नाम है के रूप में निकलता है तेजी से सीएसवी खैर तेज़ है :)

http://fastercsv.rubyforge.org

भी देखते हैं। कुछ और जानकारी

Ruby on Rails Moving from CSV to FasterCSV

+0

यह standart रूबी है 1.9 fastcsv !!! कुछ व्यवस्थापक @ sawa मेरे प्रश्न से इस महत्वपूर्ण शब्द को हटा दिया !!! – byCoder

+0

@PavelBY आप केवल उस शब्द को कोष्ठक में रखते थे, जो अन्य शवों से अलग था, और यह स्पष्ट नहीं था कि इसका क्या अर्थ था। – sawa

+0

@sawa कृपया जैसा मैंने पहले किया था कृपया करें! लेकिन जैसा कि आप कहते हैं => स्पष्ट और समझने योग्य – byCoder

0

मुझे उत्सुकता है कि फ़ाइल कितनी बड़ी है, और इसमें कितने कॉलम हैं।

CSV.foreach का उपयोग करना पसंदीदा तरीका है। मेमोरी प्रोफाइल देखना दिलचस्प होगा क्योंकि आपका ऐप चल रहा है। (कभी-कभी धीमाता प्रिंटिंग के कारण होती है, इसलिए सुनिश्चित करें कि आप इसकी आवश्यकता से अधिक नहीं करते हैं)

आप इसे प्रीप्रोसेस करने में सक्षम हो सकते हैं, और किसी भी पंक्ति को बाहर कर सकते हैं जिसमें esupp नहीं है, क्योंकि यह ऐसा लगता है कि आपका कोड केवल उन पंक्तियों की परवाह करता है। साथ ही, आप किसी भी दाहिने तरफ कॉलम को छोटा कर सकते हैं जिसकी आपको परवाह नहीं है।

एक और तकनीक अद्वितीय घटकों को इकट्ठा करने और उन्हें हैश में रखने के लिए होगी। ऐसा लगता है कि आप एक ही प्रश्न को कई बार फायर कर रहे हैं।

आपको बस इसे प्रोफ़ाइल करने की आवश्यकता है और देखें कि यह अपना समय कहां खर्च कर रहा है।

+0

निष्कर्षों के माध्यम से पूछताछ के समय मुझे पता है, लेकिन यह सीएसवी इतनी देर क्यों खुल रहा है ... संस्करण के रूप में मैं एन्कोडिंग नहीं कर रहा हूं, लेकिन यह कैसे हल करता है? मैंने इस प्रश्न के लिए भी खोला, लेकिन कोई भी – byCoder

+0

अच्छी तरह से मदद नहीं करता है, अगर हम महत्वपूर्ण विवरण नहीं जानते हैं तो यह मदद करना मुश्किल है। संवेदनशील डेटा को बाहर निकालें और महत्वपूर्ण हिस्सों के माध्यम से एक गलियारे में हम जांच कर सकते हैं। आपकी मदद करने में आसान बनाएं, और आपको कुछ मदद मिलेगी, मुझे यकीन है। –

0

जेम smart_csv देखें! यह भाग में सीएसवी फाइलें पढ़ सकता है, और फिर आप आगे की प्रक्रिया के लिए Resque नौकरियां बना सकते हैं और डेटाबेस में उन हिस्सों को सम्मिलित कर सकते हैं।

https://github.com/tilo/smarter_csv

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^