Полезно ли использовать mysql_free_result ($ result)?

Мне известно, что вся связанная результирующая память автоматически освобождается в конце выполнения script. Но рекомендуете ли вы его использовать, если я использую довольно много подобных действий, как показано ниже?

$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);**  
  }
}

Спасибо.

Ответ 1

Указание документации mysql_free_result:

mysql_free_result() нужно только если вы обеспокоены тем, как много запросов используется для запросов которые возвращают большие результирующие множества.
Все ассоциированная память результатов автоматически освобождается в конце script выполнение.


Таким образом, если в документации говорится, что вообще не нужно вызывать эту функцию, я бы сказал, что это действительно не нужно, ни хорошей практики, чтобы назвать ее; -)

И просто сказать: я почти никогда не называю эту функцию; память освобождается в конце script, и каждый script не должен есть слишком много памяти.
Исключением могут быть длительные партии, которые должны иметь дело с большими объемами данных, хотя...

Ответ 2

Да, рекомендуется использовать mysql_free_result($result). Указанная документация в принятом ответе неточна. Об этом говорит документация, но это не имеет никакого смысла. Вот что он говорит:

mysql_free_result() нужно только вызывать, если вас беспокоит, сколько памяти используется для запросов, возвращающих большие результирующие наборы. Вся связанная память результатов автоматически освобождается в конце выполнения script.

Первая часть первого предложения верна. Это правда, что вам не нужно использовать его по другим причинам, кроме проблем с памятью. Проблемы с памятью - единственная причина для ее использования. Однако вторая часть первого предложения не имеет никакого смысла. Утверждение состоит в том, что вы будете беспокоиться только о памяти для запросов, которые возвращают большие результирующие множества. Это очень вводит в заблуждение, так как существуют другие распространенные сценарии, в которых память вызывает беспокойство, а вызов mysql_free_result() - очень хорошая практика. Запросы в любое время могут запускаться неизвестное количество раз, все больше и больше памяти будут израсходованы, если вы не вызываете mysql_free_result(). Поэтому, если вы выполняете свой запрос в цикле или из функции или метода, обычно рекомендуется называть mysql_free_result(). Вам просто нужно быть осторожным, чтобы не освободить результат до тех пор, пока он больше не будет использоваться. Вы можете защитить себя от необходимости думать о том, когда и как его использовать, создавая собственные функции select() и ex(), чтобы вы не работали напрямую с наборами результатов. (Ни один из кодов здесь не соответствует именно тому, как я его написал бы, это более наглядно. Вы можете захотеть поместить их в класс или специальное пространство имен, а также сбросить другой тип исключения или взять дополнительные параметры, такие как $class_name, и др.)

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

Теперь, если вы вызываете только select() и ex(), вы просто имеете дело с нормальными объектными переменными и только с нормальной памятью, а не с ручным управлением памятью. Вам все равно придется думать о нормальных проблемах с памятью, например о том, сколько памяти используется массивом объектов. После того, как переменная выходит за пределы области видимости или вручную задает ее значение null, она становится доступной для сбора мусора, поэтому PHP позаботится об этом для вас. Вы все равно можете установить его значение null до того, как оно выйдет за пределы области видимости, если ваш код больше не использует его, и после него следуют операции, которые используют неизвестный объем памяти, такой как циклы и другие вызовы функций. Я не знаю, как результирующие наборы и функции, работающие над ними, реализуются под капотом (и даже если бы я это сделал, это могло измениться с разными/будущими версиями PHP и MySQL), поэтому существует возможность, что функция select() приблизительно удваивает объем памяти, используемый непосредственно перед вызовом mysql_free_result($rs). Однако использование select() по-прежнему устраняет то, что обычно является основной проблемой для все большего количества памяти, используемой во время циклов и различных вызовов функций. Если вас беспокоит этот потенциал для использования двойной памяти, и вы работаете только с одной строкой за одну итерацию, вы можете сделать каждую() функцию, которая не будет удваивать использование вашей памяти, и будет по-прежнему защищать вас от думая о mysql_free_result():

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

Вы можете использовать его следующим образом:

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

Другим преимуществом использования each() является то, что он ничего не возвращает, поэтому вам не нужно думать о том, нужно ли устанавливать возвращаемое значение в значение null позже.

Ответ 3

Это зависит от того, насколько велики ваши запросы и сколько запросов вы запускаете. PHP освобождает память в конце script (s) автоматически, но не во время прогона. Поэтому, если у вас есть большой объем данных, поступающих из запроса, лучше освободите результат вручную.

Я бы сказал: ДА, это хорошая практика, потому что вы заботитесь о памяти во время разработки или ваших скриптов, и именно это делает хорошего разработчика: -)

Ответ 4

Ответ, конечно, ДА в mysqli.
Взгляните на PHP mysqli_free_result documentation:

Вы всегда должны освобождать свой результат с помощью mysqli_free_result(), когда ваш конечный объект больше не нужен.

Я тестировал его с помощью функции memory_get_usage:

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

И это результат:

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

И здесь мы говорим о 151,344 bytes памяти только в строках таблицы 1000 таблицы mysql. Как насчет миллиона строк и как это думать о крупных проектах?
mysqli_free_result() предназначен не только для большого объема данных, но и для небольших проектов.