php सिद्धांत में तालिका से सभी पंक्तियां पुनर्प्राप्त करें




symfony doctrine2 (3)

इस दृष्टिकोण का उपयोग करने की कोशिश करें:

foreach ($query as $contractor) {
    // doing something

    $this->getDefaultEntityManager()->detach($contractor);
    $this->getDefaultEntityManager()->clear($contractor);
    unset($contractor); // tell to the gc the object is not in use anymore

}

उममीद है कि इससे मदद मिलेगी

मेरे पास 100 000 + पंक्तियों के साथ तालिका है, और मैं सिद्धांत में इसे सभी का चयन करना चाहता हूं और प्रत्येक पंक्ति के साथ कुछ कार्य करना चाहता हूँ, सिम्फनी 2 में सिद्धांत के साथ मैं इस प्रश्न के साथ करने का प्रयास करता हूं:

    $query = $this->getDefaultEntityManager()
        ->getRepository('AppBundle:Contractor')
        ->createQueryBuilder('c')
        ->getQuery()->iterate();

    foreach ($query as $contractor) {
        // doing something
    }

लेकिन फिर मुझे स्मृति रिसाव मिलता है, क्योंकि मुझे लगता है कि यह स्मृति में सभी डेटा लिखा है

मुझे एडीओडब में और अनुभव है, जब मैं ऐसा करता हूं:

$result = $ADOdbObject->Execute('SELECT * FROM contractors');
   while ($arrRow = $result->fetchRow()) {
        // do some action
   }

मुझे कोई स्मृति रिसाव नहीं मिला

तो तालिका से सभी डेटा का चयन कैसे करें और क्या सिम्फनी 2 में सिद्धांत के साथ मेमोरी रिसाव नहीं मिलता?

प्रश्न संपादित करें

जब मैं foreach को हटाने की कोशिश करता हूं और फिर से फिर से काम करता हूं, तो मुझे स्मृति रिसाव भी मिलता है:

$query = $this->getDefaultEntityManager()
            ->getRepository('AppBundle:Contractor')
            ->createQueryBuilder('c')
            ->getQuery()->iterate();

यदि आपको वास्तव में सभी रिकॉर्ड प्राप्त करने की आवश्यकता है, तो मैं आपको डेटाबेस_कनेक्शन का सीधे उपयोग करने का सुझाव देता हूं। अपने इंटरफेस को देखो और उस विधि का चयन करें जो सभी डेटा को स्मृति में लोड नहीं करेगा (और आपकी इकाई को रिकॉर्ड मैप नहीं करेगा)।

आप ऐसा कुछ इस्तेमाल कर सकते हैं (मान लें कि यह कोड नियंत्रक में है):

$db = $this->get('database_connection');
$query = 'select * from <your_table>';
$sth = $db->prepare($query);
$sth->execute();
while($row = $sth->fetch()) {
    // some stuff
}

शायद यह आपके लिए क्या आवश्यक नहीं है क्योंकि आप सभी संग्रहों को संभालने के बाद ऑब्जेक्ट चाहते हैं। लेकिन शायद आपको वस्तुओं की ज़रूरत नहीं है फिर भी इस बारे में सोचें।


सामान्य दृष्टिकोण पुनरावृत्त का उपयोग करना है ()

$q = $this->getDefaultEntityManager()->createQuery('select u from AppBundle:Contractor c');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
    // do something
}

हालांकि, सिद्धांत प्रलेखन कहते हैं कि यह अभी भी त्रुटियों का परिणाम निकाल सकता है।

परिणाम पूरी तरह से डेटाबेस क्लाइंट / कनेक्शन द्वारा पूरी तरह से बफर किया जा सकता है जो अतिरिक्त मेमोरी को आवंटित करता है जो कि PHP प्रक्रिया को दिखाई नहीं दे रहा है। बड़े सेटों के लिए यह आसानी से बिना किसी कारण के कारण प्रक्रिया को मार सकता है।

इसका आसान तरीका ऑफसेट और सीमाओं के साथ छोटे प्रश्नों को बनाने के लिए होगा

//get the count of the whole query first
$qb = $this->getDefaultEntityManager();
$qb->select('COUNT(u)')->from('AppBundle:Contractor', 'c');
$count = $qb->getQuery()->getSingleScalarResult();

//lets say we go in steps of 1000 to have no memory leak
$limit = 1000;
$offset = 0;

//loop every 1000 > create a query > loop the result > repeat
while ($offset < $count){
    $qb->select('u')
        ->from('AppBundle:Contractor', 'c')
        ->setMaxResults($limit)
        ->setFirstResult($offset);
    $result = $qb->getQuery()->getResult();
    foreach ($result as $contractor) {
        // do something
    }
    $offset += $limit;
}

इस भारी डेटासेट के साथ यह अधिकतम निष्पादन समय पर जाने की संभावना है, जो डिफ़ॉल्ट रूप से 30 सेकंड है। इसलिए अपने php.ini में मैन्युअल रूप से set_time_limit को बदलना सुनिश्चित करें। यदि आप सभी ज्ञात पैटर्न के साथ सभी डेटासेट को अपडेट करना चाहते हैं, तो आपको PHP में परिणाम को पाशन और संपादन के बजाय एक बड़ी अद्यतन क्वेरी लिखना पर विचार करना चाहिए।





adodb-php