2012-07-29 14 views
8

saklanır ve mysqli_result sonuçları almak nasıl, bellek kullanımı son derece küçüktür. Ancak, sorgudaki tüm satırları çağrışımsal bir diziye aldığımda, bellek kullanımı çok yüksek olur.PHP: Sorgu sonuçları Ben veritabanına bir sorgu yaptığında mysqli_result

<?php 
    require_once("../config.php"); //db connection config 
    $db = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_DBASE); 

    $query ="select * from table_name"; 
    if($r = $db->query($query)){ 
    echo "MEMORY USAGE before : ". memory_get_usage()."<br><br>"; 
    $rows = array(); 
    while($row = $r->fetch_assoc()){ 

     $rows[]= $row; 
    } 
    echo "MEMORY USAGE after : ". memory_get_usage()."<br><br>"; 


    //before: 660880 
    //after: 114655768 
    // # of records: around 30 thousands 
?> 

Bu çok sonuç saklamak tüketen çok anı olduğunu bana mantıklı, ama sadece mysqli_result çok küçük nasıl oluyor merak ediyorum. Fetch_assoc çağrıldığında, sonuçların dbase'e sorgulanması mümkün olamaz. Öyleyse, sonuçta bellekte saklanan sonuçlar. Yayınladığınız

while($row = $r->fetch_assoc()){ 
    //Do whatever you need with the record, then: 
    unset($row); 
} 

yolu $rows büyük bir dizi topluyor ve bellek kullanımı olduğunu yansıtır:

+1

ben 'mysql_ *' fonksiyonları seferde sunucudan sonucu tüm satırları getirme olduğunu okumuştum. Ancak PDO (ve muhtemelen mysqli) her bir satırı talep üzerine alır. Böylece her çağrı için biraz hafıza kullanacaksınız. Ancak her satırı bir dizide saklarsınız, bu nedenle bellek kullanımınızın birikir anlamına gelir. –

+0

Bunu yapmak için her aramada mysqli, sonuç için veritabanını sorgulayacak mı? – spchuang

+1

Anlayışımdan 'query() 'dediğinizde, MySQL sorguyu gerçekleştirir ve tüm sonuç satırlarını PHP'ye döndürmeye hazırlanır. Bununla birlikte, eğer mysqli PDO'ya benziyorsa (en azından PDO'nun varsayılanı), siz çağırmayı çağırıncaya kadar satır almaya başlamaz. FetchAll() 'adını vermediğiniz sürece, her satır birer birer alınacaktır. Bu, bellek kullanımınızın, sonuçları mysqli nedeniyle değil bir dizide kaydettiğiniz anlamına gelir. –

cevap

2

sonuç alma ve bir kaynak için bir işaretçi depolanması arasında büyük bir fark vardır.

Eğer echo $r;memory_get_usage(); için ilk çağrı önce, bunu sadece bir işaretçi olduğunu fark olacaktır. Bu, sonuç kümenizin işaretçisidir. Sonuçlarınız fetch sonuçlarına kadar, sonuç kümesi aslında belleğe kaydedilmez.

Ne yapmaya çalışıyorsun ne için fetchAll() çalıştırmanızı öneririz. Bu, daha sonra daha iyi performansa sahip bir yöntemle sonuçlanacak ve böylece PHP'deki bir döngüden ziyade mysqli uzantısında (C Kütüphanesi) rehine edildiği için 1 yönteme neden olacaktır.

Ayrıca onlarla bittiğinde bellekten sonuçlarınızı temizlemek için ücretsiz sonuçlar işlevini kullanabilirsiniz. Bu, alışkınsanız Java'da bir imleci kapatmak gibidir.

+0

Teşekkürler. Bu çok yardımcı! :) – spchuang

+0

Peki, neden kaynak bellek kullanımına gerçekten eklenmiş değil?Kaynak bellek alanı kullanıyor ... Yoksa diske mi yazılıyor? –

+0

Getirimi çağırmadan önce echo'ing '$ r' ile, MySQL sorgu sonuçları için yer ayırdı, ancak PHP'yi değil. PHP, getirmeyi çağırdığınızda sonuçları yalnızca bellek alanına atayacaktır. –

1

Bu yerine göre sizde kalmalı.

+0

Ne demek istediğini biliyorum ve bu kesinlikle fetch_assoc() için orijinal niyetidir. Sorun şu ki sonuca ulaşacağım ve onunla bir şeyler yapacağım ve kayıtları görüntülemek için (MVC anlamında) görüntülemeye geçeceğim. Sanırım uygulamamı değiştirebilirim, böylece bir kayıt bir seferde görüntülenebilir. – spchuang

+0

Bu akıllıca olurdu :) – Niloct

+0

Teşekkürler. Bu bir problem çünkü modeller ile doğrudan iletişim kurmayı engellemeye çalışıyorum, bu yüzden veriyi iletmek için aralarında bir denetleyici var. Ne o zaman yapmanız gereken size pagination çeşit uygulamak gerekir gibi görünüyor ~ 30 k kayıtları varsa ... her kaydı görüntülemek için – spchuang