2012-02-11 18 views
5

मैं बैच स्क्रिप्ट लिख रहा हूं और Allowed memory size of 134217728 bytes exhausted त्रुटि प्राप्त कर रहा हूं।क्यों "अनुमत स्मृति आकार समाप्त हो गया"?

मुझे समझ में नहीं आता कि स्मृति क्यों भर रही है। मैंने $row वैरिएबल को अनसेट करने का प्रयास किया, लेकिन इससे कोई चीज़ नहीं बदली। यहाँ मेरी कोड है:

// ... (sql connection) 
$result = mysql_query("SELECT * FROM large_table"); 

while ($row = mysql_fetch_array($result)) { 
    echo $row['id'] . PHP_EOL; 
    unset($row); 
} 

(सरलीकृत कोड)

क्यों स्मृति को भरने करता है, और मैं इसे कैसे बच सकते हैं?

नोट: यह एक बैच स्क्रिप्ट है। यह सामान्य है कि मुझे इस तरह के डेटा को संभालना होगा (1 मिलियन लाइनों के माध्यम से जाना)।

अद्यतन: 400 000 वें लाइन के आसपास स्मृति से बाहर होता है, तो यह लूप में कुछ होना चाहिए? यदि संभव हो तो मैं पेजिंग को लागू करने से बचना चाहता हूं।

+0

यह नहीं दिखता है जैसे आप उस कोड स्निपेट से स्मृति से बाहर चलाने चाहिए। क्या कोई अन्य चर है जो प्रत्येक पुनरावृत्ति को बढ़ा रहा है? –

+0

mysql क्वेरी वास्तव में पूरी तालिका को वापस नहीं करेगा -> जिसका अर्थ है कि परिणाम उपयोग की गई स्मृति में गिना जाएगा? – KillerX

+0

एक मूर्ख सुझाव हो सकता है, लेकिन यह केवल एक चीज है जिसके बारे में मैं सोच सकता हूं: शायद आप अपने आउटपुट बफर को फ्लश करने का प्रयास कर सकते हैं? – Martijn

उत्तर

10

http://www.php.net/manual/en/function.mysql-unbuffered-query.php (mysql_unbuffered_query()) उपयोग करने का प्रयास पूरी तालिका मेमोरी में लोड किया जा रहा है, लेकिन अभी पृष्ठांकन से बचने को रोकने के लिए: नीचे दिए गए लिंक पर एक नज़र, विशेष रूप से SELECT की LIMIT offset, limit वाक्य रचना की है।

+0

उसने ऐसा किया! आपका अंतर्ज्ञान सही था, और मुझे यह पसंद है कि यह समस्या की जड़ का जवाब देता है। –

+0

बीटीडब्ल्यू मैं स्पष्टीकरण के बिना डाउनवॉव को समझ नहीं पा रहा हूं ... मैं –

+0

की क्षतिपूर्ति करने के लिए उभरा हूं, मुझे यकीन नहीं है कि यह सही दृष्टिकोण है, लेकिन +1 क्योंकि यह मूल प्रश्न का उत्तर देता है :) – halfer

4

उदाहरण के लिए 1k परिणाम के लिए अपनी क्वेरी को सीमित करें और इसे फिर से निष्पादित करें (ऑफ़सेट के साथ) जब तक कि आप सभी तालिकाओं से गुज़र चुके न हों। आपकी वर्तमान अनसेट से कोई फर्क नहीं पड़ता है, क्योंकि प्रत्येक पंक्ति पुनरावृत्ति के दौरान प्रत्येक के साथ अधिलेखित हो जाती है, इसलिए आप इसे छोड़ सकते हैं।

$chunk_size = 1000; 
$done = 0; 

$keep_asking_for_data = true; 
do{ 
    $result = mysql_query("SELECT * FROM `large_table` LIMIT {$done}, {$chunk_size}"); 
    $num_rows = mysql_num_rows($result); 
    if($num_rows){ 
     $done += $num_rows; 
     while($row = mysql_fetch_assoc($result)){ 
      echo "{$row['id']}\n"; 
     } 
    } else { 
     $keep_asking_for_data = false; 
    } 
    mysql_free_result($result); 
}while($keep_asking_for_data); 

बस मेरे सिर पर संकलित, यह काम करता है आशा = डी

+0

मैंने वैरिएबल द्वारा उपयोग की गई मेमोरी के संग्रह को मजबूर करने के लिए अनसेट जोड़ने का प्रयास किया, जिसकी गारंटी नहीं है (PHP जीसी)। वैसे भी, दूसरे उत्तर पर टिप्पणी देखें और प्रश्न अद्यतन –

+0

अरे! "यदि संभव हो तो मैं पेजिंग को लागू करने से बचना चाहता हूं।" जब मैंने कोड बनाया था तो यह वहां नहीं था: डी – PalmTree

+0

+1 मेरे लिए अच्छा लग रहा है! – halfer

1

आप MySQL, पेज अपने परिणामों को उपयोग कर रहे हैं तो आप अपने उपलब्ध स्मृति निकास नहीं है। MySQL स्वयं ही इस मेमोरी को आपके डेटाबेस परिणामसेट के साथ ले रहा है।

http://dev.mysql.com/doc/refman/5.0/en/select.html

+0

यह एक विचार था लेकिन मैं कबूल करता हूं कि मैं इसे करने के लिए बहुत आलसी था: पी। वैसे भी, त्रुटि 400 000 वीं लाइन के आसपास होती है (प्रश्न अपडेट देखें) तो यह लूप में कुछ हो सकता है जिसे मैं ठीक कर सकता हूं? –

+0

आपके दृष्टिकोण के रूप में * कुछ * बफर करना चाहिए * बफरिंग को हटा देना ताकि पेजिंग अनावश्यक हो जाए, शायद यह करने का तरीका नहीं है, इमो। वैसे भी यह अब आसान होना चाहिए - @ पाल्मट्री ने यह आपके लिए किया है :) – halfer

+0

आपको लगता है कि पेजिंग को हटाने का यह अच्छा तरीका क्यों नहीं है? –

1

मुझे एक बड़े डेटाबेस के साथ एक ही समस्या थी। $ 400,000 रिकॉर्ड्स पर $ पंक्ति चर को अनसेट करने के बावजूद, मैं स्मृति से बाहर भाग गया, लेकिन अनबफर किए गए क्वेरी ने इसे ठीक किया।

बस दूसरों के लिए संदर्भ के लिए

(और मुझे जब मैं इसे फिर से करते हैं!), कुछ unbuffered क्वेरी उदाहरण कोड है:

$sql = "SELECT SEQ, RECTYPE, ROSTERGRP, EMPNM, EMPNUM, DT, RDUTYCAT, ADUTYCAT FROM " . 
     $tblRosters . " ORDER BY EMPNUM,DT"; 
$result = mysql_unbuffered_query($sql, $dbConn); 
$svRow = array(); 
while ($row = mysql_fetch_array($result)) 
    { 
     // your processing code here 
    } 
    // Unset, close db etc. if you are finished goes here. 
संबंधित मुद्दे