开发者

is it a good practice to use mysql_free_result($result)?

开发者 https://www.devze.com 2022-12-23 17:44 出处:网络
I am aware of that All associated result memory is automatically freed at the end of the script\'s execution. But would you recommend using it, if I am using a quite of lot of somewhat similar actions

I am aware of that All associated result memory is automatically freed at the end of the script's execution. But would you recommend using it, if I am using a quite of lot of somewhat similar actions as below?

$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);
     **m开发者_运维百科ysql_free_result($result2);**  
  }
}

Thanks.


Quoting the documentation of mysql_free_result :

mysql_free_result() only needs to be called if you are concerned about how much memory is being used for queries that return large result sets.
All associated result memory is automatically freed at the end of the script's execution.


So, if the documentation says it's generally not necessary to call that function, I would say it's not really necessary, nor good practice, to call it ;-)

And, just to say : I almost never call that function myself ; memory is freed at the end of the script, and each script should not eat too much memory.
An exception could be long-running batches that have to deal with large amounts of data, though...


Yes, it is good practice to use mysql_free_result($result). The quoted documentation in the accepted answer is inaccurate. That is what the documentation says, but that doesn't make any sense. Here is what it says:

mysql_free_result() only needs to be called if you are concerned about how much memory is being used for queries that return large result sets. All associated result memory is automatically freed at the end of the script's execution.

The first part of the first sentence is correct. It is true that you don't need to use it for reasons other than memory concerns. Memory concerns are the only reason to use it. However, the second part of the first sentence doesn't make any sense. The claim is that you would only be concerned about memory for queries that return large result sets. This is very misleading as there are other common scenarios where memory is a concern and calling mysql_free_result() is very good practice. Any time queries may be run an unknown number of times, more and more memory will be used up if you don't call mysql_free_result(). So if you run your query in a loop, or from a function or method, it is usually a good idea to call mysql_free_result(). You just have to be careful not to free the result until after it will not be used anymore. You can shield yourself from having to think about when and how to use it by making your own select() and ex() functions so you are not working directly with result sets. (None of the code here is exactly the way I would actually write it, it is more illustrative. You may want to put these in a class or special namespace, and throw a different Exception type, or take additional parameters like $class_name, etc.)

// 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;
}

Now if you only call select() and ex(), you are just dealing with normal object variables and only normal memory concerns instead of manual memory management. You still have to think about normal memory concerns like how much memory is in use by the array of objects. After the variable goes out of scope, or you manually set it to null, it become available for garbage collection so PHP takes care of that for you. You may still want to set it to null before it goes out of scope if your code does not use it anymore and there are operations following it that use up an unknown amount of memory such as loops and other function calls. I don't know how result sets and functions operating on them are implemented under the hood (and even if I did, this could change with different/future versions of PHP and MySQL), so there is the possibility that the select() function approximately doubles the amount of memory used just before mysql_free_result($rs) is called. However using select() still eliminates what us usually the primary concern of more and more memory being used during loops and various function calls. If you are concerned about this potential for double memory usage, and you are only working with one row at a time over a single iteration, you can make an each() function that will not double your memory usage, and will still shield you from thinking about mysql_free_result():

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

You can use it like this:

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

Another advantage of using each() is that it does not return anything, so you don't have to think about whether or not to set the return value to null later.


The answer is of course YES in mysqli.
Take a look at PHP mysqli_free_result documentation:

You should always free your result with mysqli_free_result(), when your result object is not needed anymore.

I used to test it with memory_get_usage function:

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

And it is the result:

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

And here, we are talking about 151,344 bytes of memory in only 1000 rows of mysql table. How about a million rows and how is it to think about large projects?
mysqli_free_result() is not only for large amount of data, it is also a good practice for small projects.


It depends on how large your queries are or how many queries you run. PHP frees the memory at the end of the script(s) automatically, but not during the run. So if you have a large amount of data comming from a query, better free the result manually.

I would say: YES, it is good practice because you care about memory during the development or your scripts and that is what makes a good developer :-)

0

精彩评论

暂无评论...
验证码 换一张
取 消