2010-03-23 15 views
11

Ich bin mir dessen bewusst, dass alle zugehörigen Ergebnisspeicher automatisch am Ende der Skriptausführung freigegeben werden. Aber würdest du es empfehlen, wenn ich ziemlich viele ähnliche Aktionen wie unten verwende?

$sql = "select * from products"; 
$result = mysql_query($sql); 
if($result && mysql_num_rows($result) > 0) { 
    while($data = mysql_fetch_assoc($result)) { 
    $sql2 = "insert into another_table set product_id = '".$data['product_id']."' 
       , product_name = '".$data['product_name']."' 
      "; 
    $result2 = mysql_query($sql2); 
    **mysql_free_result($result2);** 
    } 
} 

Danke.

+3

Ich hoffe sehr, dass der Code, den Sie zur Veranschaulichung zitieren nur - dies alles in einer einzigen SQL-Abfrage durchgeführt werden kann: INSERT INTO another_table (product_id, product_name) SELECT product_id, product_name FROM Produkte – symcbean

Antwort

18

Zitiert in der Dokumentation von mysql_free_result:

mysql_free_result() braucht nur aufgerufen werden, wenn Sie sind besorgt darüber, wie viel Speicher für Abfragen verwendet werden die große Ergebnismengen zurück.
Alle zugeordneten Ergebnisspeicher ist automatisch am Ende der Skriptausführung freigegeben.


Also, wenn die Dokumentation sagt, dass es im Allgemeinen nicht notwendig ist, um diese Funktion zu nennen, würde ich sagen, es ist nicht wirklich notwendig, noch gute Praxis, es zu nennen ;-)

Und nur zu sagen, : Ich nenne diese Funktion fast nie selbst; Speicher wird am Ende des Skripts freigegeben, und jedes Skript sollte nicht essen zu viel Speicher.
Eine Ausnahme könnten lange laufende Stapel sein, die große Datenmengen verarbeiten müssen ...

1

Es hängt davon ab, wie groß Ihre Abfragen sind oder wie viele Abfragen Sie ausführen. PHP gibt den Speicher am Ende des Skripts automatisch frei, aber nicht während des Laufs. Wenn Sie also eine große Menge an Daten von einer Abfrage erhalten, sollten Sie das Ergebnis manuell freigeben.

Ich würde sagen: ja, es gute Praxis ist, weil Sie über das Gedächtnis während der Entwicklung oder Ihre Skripte kümmern und das ist, was :-)

+0

Vertrauen Sie mir, wenn ich sage, dass „mysql_free_result () "Anrufe allein sind nicht unbedingt ein guter Indikator für einen guten Entwickler. – Kzqai

4

einen guten Entwickler macht Ja, es gute Praxis ist mysql_free_result($result) zu verwenden. Die zitierte Dokumentation in der angenommenen Antwort ist ungenau. Das sagt die Dokumentation, aber das ergibt keinen Sinn. Hier ist, was es says:

mysql_free_result() nur aufgerufen werden muss, wenn Sie sind besorgt darüber, wie viel Speicher für Abfragen verwendet werden, die große Ergebnismengen zurückgeben. Der gesamte zugehörige Ergebnisspeicher wird am Ende der Skriptausführung automatisch freigegeben.

Der erste Teil des ersten Satzes ist korrekt. Es ist wahr, dass Sie es aus anderen Gründen als aus Speichergründen nicht verwenden müssen. Speicherprobleme sind der einzige Grund, es zu benutzen. Der zweite Teil des ersten Satzes macht jedoch keinen Sinn. Die Behauptung ist, dass Sie sich nur um den Speicher für Abfragen kümmern würden, die große Ergebnismengen zurückgeben. Dies ist sehr irreführend, da es andere häufige Szenarien gibt, in denen Speicher ein Problem darstellt und das Anrufen mysql_free_result() eine sehr gute Praxis ist. Jedes Mal, wenn Abfragen eine unbekannte Anzahl von Malen ausgeführt werden, mehr und mehr Speicher verbraucht wird, wenn Sie nicht mysql_free_result() aufrufen. Wenn Sie also Ihre Abfrage in einer Schleife oder von einer Funktion oder Methode ausführen, ist es normalerweise eine gute Idee, mysql_free_result() aufzurufen. Sie müssen nur darauf achten, das Ergebnis nicht zu löschen, bis es nicht mehr verwendet wird.Sie können sich davor schützen, dass Sie darüber nachdenken müssen, wann und wie Sie es verwenden, indem Sie Ihre eigenen Funktionen select() und ex() erstellen, so dass Sie nicht direkt mit Ergebnismengen arbeiten. (Keiner der Code hier ist genau so, wie ich es tatsächlich schreiben würde, es ist anschaulicher. Sie können diese in eine Klasse oder einen speziellen Namespace einfügen und einen anderen Ausnahmetyp werfen, oder zusätzliche Parameter wie $class_name, etc nur den Umgang mit normalen Objektvariablen und nur normale Speicher Bedenken statt manueller Speicherverwaltung).

// call this for select queries that do not modify anything 
function select($sql) { 
    $array= array(); 
    $rs= query($sql); 
    while($o= mysql_fetch_object($rs)) 
     $array[]= $o; 
    mysql_free_result($rs); 
    return $array; 
} 

// call this for queries that modify data 
function ex($sql) { 
    query($sql); 
    return mysql_affected_rows(); 
} 

function query($sql) { 
    $rs= mysql_query($sql); 
    if($rs === false) { 
     throw new Exception("MySQL query error - SQL: \"$sql\" - Error Number: " 
      .mysql_errno()." - Error Message: ".mysql_error()); 
    } 
    return $rs; 
} 

Nun, wenn Sie rufen nur select() und ex(), Sie sind. Sie müssen immer noch über normale Speicherprobleme nachdenken, z. B. wie viel Speicher das Array von Objekten belegt. Nachdem die Variable den Gültigkeitsbereich verlassen hat oder Sie sie manuell auf null setzen, wird sie für die Garbage Collection verfügbar, sodass PHP diese für Sie übernimmt. Sie können es immer noch auf NULL setzen, bevor es den Gültigkeitsbereich verlässt, wenn Ihr Code es nicht mehr verwendet und es Operationen gibt, die darauf folgen und eine unbekannte Menge an Speicher wie Schleifen und andere Funktionsaufrufe verbrauchen. Ich weiß nicht, wie die Ergebnissätze und Funktionen, die auf ihnen ausgeführt werden, unter der Haube implementiert sind (und selbst wenn, könnte sich dies mit anderen/zukünftigen Versionen von PHP und MySQL ändern), also besteht die Möglichkeit, dass sich die select() Funktion ungefähr verdoppelt die Menge an Speicher, die kurz vor mysql_free_result($rs) verwendet wird, wird aufgerufen. Die Verwendung von select() beseitigt jedoch immer noch das, was uns normalerweise am wichtigsten ist, wenn mehr und mehr Speicher während Schleifen und verschiedenen Funktionsaufrufen verwendet wird. Wenn Sie Bedenken hinsichtlich dieses Potenzials für die doppelte Speichernutzung haben und nur über eine einzige Iteration mit jeweils einer Zeile gleichzeitig arbeiten, können Sie eine each() - Funktion erstellen, die die Speicherbelegung nicht verdoppelt und die Sie weiterhin abschirmt nachdenken über mysql_free_result():

each("SELECT * FROM users", function($user) { 
    echo $user->username."<BR>"; 
}); 

Ein weiterer Vorteil der Verwendung von each() ist, dass es nichts zurückliefert, so muss man nicht darüber nachdenken, ob:

each($sql,$fun) { 
    $rs= query($sql); 
    while($o= mysql_fetch_object($rs)) 
     $fun($o); 
    mysql_free_result($rs); 
} 

Sie es wie folgt verwenden können oder den Rückgabewert später nicht auf null setzen.

0

Die Antwort ist natürlich ja in mysqli.
Werfen Sie einen Blick auf PHP mysqli_free_result documentation:

Sie immer Ihr Ergebnis mit mysqli_free_result() befreien sollen, wenn Ihr Ergebnis Objekt nicht mehr benötigt wird.

habe ich es mit memory_get_usage Funktion zu testen:

echo '<br>before mysqli free result: '.memory_get_usage(); 
mysqli_free_result($query[1]); 
echo '<br>after mysqli free result'.memory_get_usage(); 

Und es ist das Ergebnis:

before mysqli free result:2110088 
after mysqli free result:1958744 

Und hier sind wir nur 1000 Reihen in etwa 151,344 bytes Speicher sprechen von MySQL-Tabelle. Wie wäre es mit einer Million Zeilen und wie ist es, über große Projekte nachzudenken?
mysqli_free_result() ist nicht nur für große Datenmengen, es ist auch eine gute Praxis für kleine Projekte.

Verwandte Themen