Pg free result: примеры (PHP)
pg_free_result(PgSql\Result $result): boolФункция pg_free_result() в PHP освобождает память, занятую ресурсом результата запроса к базе данных PostgreSQL. Использование функции необходимо при работе с большими результатами запросов для предотвращения утечек памяти.
Функция вызывается после обработки данных, полученных с помощью pg_query() или подобных функций. Явное освобождение ресурсов особенно полезно в скриптах, выполняющих множество запросов или обрабатывающих большие объемы информации.
Функция принимает один обязательный параметр:
- $result (ресурс PostgreSQL) - дескриптор результата запроса, возвращаемый функциями pg_query(), pg_query_params() или pg_execute().
Возвращаемое значение — логическое true после успешного выполнения или false в случае ошибки.
Функция имеет простой синтаксис и вызывается после завершения работы с данными результата запроса.
После получения и обработки строк запроса память можно освободить.
$connection = pg_connect("host=localhost dbname=test user=postgres");
$result = pg_query($connection, "SELECT id, name FROM users");
// Обработка результата
while ($row = pg_fetch_assoc($result)) {
echo $row['id'] . ': ' . $row['name'] . "\n";
}
// Освобождение памяти
$freed = pg_free_result($result);
echo 'Ресурс освобожден: ' . ($freed ? 'да' : 'нет');1: Иван Петров 2: Мария Сидорова Ресурс освобожден: да
Проверка типа аргумента перед вызовом функции.
$result = pg_query($connection, "SELECT NOW()");
if (is_resource($result) || $result instanceof PgSql\Result) {
pg_free_result($result);
echo 'Память результата запроса освобождена.';
} else {
echo 'Неверный ресурс результата.';
}Память результата запроса освобождена.
В PHP отсутствуют прямые аналоги pg_free_result() для расширения PostgreSQL. Однако освобождение памяти происходит автоматически при завершении скрипта или при присвоении переменной нового значения.
- unset($result) - уничтожает переменную, но не всегда немедленно освобождает память, занятую ресурсом. Явный вызов pg_free_result() более предсказуем.
- Для MySQLi существует функция mysqli_free_result(), выполняющая аналогичную роль для результатов MySQL.
Использование pg_free_result() предпочтительно в длительных скриптах, например, в демонах или при обработке большого количества данных, где контроль за памятью критически важен.
Концепция освобождения памяти, занятой результатами запроса, существует во многих средах разработки.
import psycopg2
conn = psycopg2.connect("dbname=test user=postgres")
cur = conn.cursor()
cur.execute("SELECT * FROM users")
rows = cur.fetchall() # Данные полностью загружены в память
cur.close() # Курсор закрывается, ресурсы освобождаются
# Явной функции для освобождения только результата нет, управление памятью - за сборщиком мусора.const { Client } = require('pg');
const client = new Client();
await client.connect();
const res = await client.query('SELECT * FROM users');
console.log(res.rows); // Данные в массиве rows
// Явного освобождения не требуется. Объект результата будет удален сборщиком мусора.
// Однако для больших результатов можно использовать потоковое чтение.В самом MySQL нет прямой SQL-команды для освобождения памяти на стороне клиента. В CLI-клиенте или коннекторах (например, C API) существуют аналогичные функции (например, mysql_free_result()). В PHP для MySQLi это mysqli_free_result().
Отличие PHP функции в ее явности и направленности именно на управление памятью в рамках одного расширения (pgsql).
Ошибки чаще всего связаны с попыткой использования ресурса после его освобождения или передачей неверного аргумента.
$result = pg_query($connection, "SELECT 1");
pg_free_result($result);
$row = pg_fetch_row($result); // Ошибка: ресурс результата недействителен
echo 'Эта строка не выполнится.';Warning: pg_fetch_row(): supplied resource is not a valid PostgreSQL result resource in ...
$not_a_result = null;
$freed = pg_free_result($not_a_result); // Вызовет TypeError в PHP 8
echo 'Результат: ' . $freed;TypeError: pg_free_result(): Argument #1 ($result) must be of type PgSql\Result, null given
$result = pg_query($connection, "SELECT 1");
pg_free_result($result); // Первый вызов - успешен
$freedAgain = pg_free_result($result); // Второй вызов вернет false
echo 'Второе освобождение: ' . ($freedAgain ? 'успешно' : 'неудачно');Второе освобождение: неудачно
В PHP 8.0 API расширения PostgreSQL было модернизировано. Вместо ресурсов (resource) теперь используются объекты класса PgSql\Result. Функция pg_free_result() продолжает работать, но принимает и возвращает объект вместо ресурса.
- До PHP 8.0: pg_free_result(resource $result): bool
- Начиная с PHP 8.0: pg_free_result(PgSql\Result $result): bool
Это изменение повышает типобезопасность кода. Попытка передать неверный тип аргумента вызывает TypeError, а не предупреждение.
При последовательном выполнении множества запросов в цикле важно своевременно освобождать память.
$queries = ["SELECT * FROM logs_202301", "SELECT * FROM logs_202302", "SELECT * FROM logs_202303"];
foreach ($queries as $query) {
$result = pg_query($connection, $query);
if (!$result) {
continue;
}
// Какая-то минимальная обработка...
$count = pg_num_rows($result);
echo "Найдено записей: $count\n";
// Освобождаем память перед следующей итерацией
pg_free_result($result);
}Найдено записей: 150 Найдено записей: 200 Найдено записей: 175
При использовании курсоров PostgreSQL результат основной функции его создания также требует очистки.
// Создание курсора
$result = pg_query($connection, "DECLARE my_cursor CURSOR FOR SELECT * FROM large_table");
// Результат создания курсора нужно освободить
pg_free_result($result);
// Далее работа с курсором через FETCH...
$fetchRes = pg_query($connection, "FETCH 100 FROM my_cursor");
// Обработка данных из fetchRes...
pg_free_result($fetchRes);
// Закрытие курсора
$closeRes = pg_query($connection, "CLOSE my_cursor");
pg_free_result($closeRes);Создание функции, которая гарантированно освобождает результат после его обработки коллбэком.
function processAndFreeResult($connection, $query, callable $processor) {
$result = pg_query($connection, $query);
if (!$result) {
return false;
}
try {
// Вызов пользовательской функции обработки
$processorResult = $processor($result);
return $processorResult;
} finally {
// Гарантированное освобождение ресурса, даже если в коллбэке было исключение
pg_free_result($result);
}
}
// Пример вызова
$conn = pg_connect("...");
$data = processAndFreeResult($conn, "SELECT * FROM products", function ($res) {
return pg_fetch_all($res);
});
print_r($data);Array
(
[0] => Array
(
[id] => 1
[name] => Товар 1
)
...
)function safePgFreeResult($result) {
if ($result instanceof PgSql\Result || (is_resource($result) && get_resource_type($result) === 'pgsql result')) {
return pg_free_result($result);
}
return false;
}
$res = pg_query($connection, "SELECT 1");
safePgFreeResult($res);
// Безопасно для PHP 7 и 8