2011-09-06 9 views
19

फिलहाल मैं एक बहुत बड़ी सीएसवी फ़ाइल के लिए एक आयात स्क्रिप्ट लिख रहा हूं। समस्या यह है कि यह समय-समय पर थोड़ी देर बाद बंद हो जाती है या यह स्मृति त्रुटि फेंकता है।टाइमआउट और मेमोरी त्रुटि के बिना बहुत बड़ी सीएसवी फ़ाइल को संसाधित करें

मेरा आइडिया अब "100 लाइनों" चरणों में सीएसवी फ़ाइल को पार्स करने के लिए था और 100 लाइनों के बाद स्वचालित रूप से स्क्रिप्ट को याद किया गया। मैंने इसे हेडर (स्थान ...) के साथ प्राप्त करने की कोशिश की और वर्तमान लाइन को प्राप्त करने के साथ पास किया लेकिन यह काम नहीं कर सका क्योंकि मैं चाहता हूं।

क्या इसका कोई बेहतर तरीका है या क्या किसी को यह पता है कि स्मृति त्रुटि और टाइमआउट से कैसे छुटकारा पाना है?

+2

कितना बड़ा अपनी CSV फ़ाइल है? आपको इसे डेटाबेस में आयात करने की आवश्यकता है? –

+0

http://stackoverflow.com/a/22744300/2037323 पर मेरा उत्तर देखें जिसमें कुछ तुलना भी शामिल है। –

उत्तर

44

मैंने स्ट्रीम-वार-तरीके से 120 एमबी सीएसवी पढ़ने के लिए fgetcsv का उपयोग किया है (क्या यह सही अंग्रेजी है?)। वह रेखा से लाइन में पढ़ता है और फिर मैंने प्रत्येक पंक्ति को डेटाबेस में डाला है। इस तरह प्रत्येक पुनरावृत्ति पर स्मृति में केवल एक पंक्ति होती है। स्क्रिप्ट को अभी भी 20 मिनट की आवश्यकता है। चलाने के लिए। हो सकता है कि मैं अगली बार पाइथन का प्रयास करूं ... एक सरणी में एक बड़ी सीएसवी फ़ाइल लोड करने की कोशिश न करें, जो वास्तव में बहुत सारी स्मृति का उपभोग करेगी।

// WDI_GDF_Data.csv (120.4MB) are the World Bank collection of development indicators: 
// http://data.worldbank.org/data-catalog/world-development-indicators 
if(($handle = fopen('WDI_GDF_Data.csv', 'r')) !== false) 
{ 
    // get the first row, which contains the column-titles (if necessary) 
    $header = fgetcsv($handle); 

    // loop through the file line-by-line 
    while(($data = fgetcsv($handle)) !== false) 
    { 
     // resort/rewrite data and insert into DB here 
     // try to use conditions sparingly here, as those will cause slow-performance 

     // I don't know if this is really necessary, but it couldn't harm; 
     // see also: http://php.net/manual/en/features.gc.php 
     unset($data); 
    } 
    fclose($handle); 
} 
12

यदि आपको परवाह नहीं है कि यह कितना समय लगता है और इसकी कितनी मेमोरी की आवश्यकता है, तो आप इस स्क्रिप्ट के लिए मूल्यों को आसानी से बढ़ा सकते हैं। समारोह memory_get_usage() आप पता कर सकते हैं कि कितना स्मृति अपनी स्क्रिप्ट memory_limit के लिए एक अच्छा मूल्य खोजने के लिए की जरूरत है के साथ

ini_set('memory_limit', '512M'); 
ini_set('max_execution_time', '180'); 

: बस अपनी स्क्रिप्ट के शीर्ष पर निम्नलिखित पंक्तियाँ जोड़ें।

आप fgets() पर भी एक नज़र डालना चाहते हैं जो आपको लाइन द्वारा फ़ाइल लाइन पढ़ने की अनुमति देता है। मुझे यकीन नहीं है कि अगर कम स्मृति लेती है, लेकिन मुझे सच में लगता है कि यह काम करेगा। लेकिन यहां तक ​​कि इस मामले में आपको max_execution_time को उच्च मान में बढ़ाना होगा।

+1

यह निश्चित रूप से केवल एक अच्छा दृष्टिकोण है यदि आप जानते हैं कि फ़ाइल हमेशा एक ही आकार का है। –

+3

यदि आप जानते हैं कि यह एक सापेक्ष आकार से बड़ा नहीं है, तो यह भी काम करता है। – 2ndkauboy

-2

ओह। मूर्खतापूर्ण वेब इंटरफेस के माध्यम से, इस स्क्रिप्ट को सीएलआई के रूप में नहीं बुलाएं। इसलिए, कोई निष्पादन समय सीमा इसे प्रभावित नहीं करेगी।
और हमेशा के लिए पार्स किए गए परिणाम न रखें, लेकिन उन्हें तुरंत लिखें - इसलिए, आप स्मृति सीमा से भी प्रभावित नहीं होंगे।

12

मैं फ़ाइल को अपलोड करने और mysql के डेटा लोड स्थानीय क्वेरी एक तेजी से समाधान जैसे का उपयोग कर डालने खोजें:

$sql = "LOAD DATA LOCAL INFILE '/path/to/file.csv' 
     REPLACE INTO TABLE table_name FIELDS TERMINATED BY ',' 
     ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES"; 
    $result = $mysqli->query($sql); 
+0

वाह मैं 5 मिनट से + 64 सेकंड रिकॉर्ड सीएसवी आयात करने के लिए 5 सेकंड से कम आयात करने के लिए चला गया। यह शानदार है! – Iznogood