Привет! Возникла проблема - при чтении из большой таблицы базы данных скрипт выдаёт ошибку:
Allow memory...
Код следующий:
$query = mysql_query('SELECT * FROM `table`;');
while ($res = mysql_fetch_array($query))
{
echo $res['id'] . ',';
unset($res);
}
Можно ли как-то оптимизировать, чтобы не получать данную ошибку?
Очевидно, что большое кол-во данных требует большого кол-ва памяти при работе метода. Для минимального использования памяти на стороне клиентского приложения относительно базы используются курсоры, он у вас используется при помощи функции mysql_fetch_array, которая извлекает следующий результат из курсора.
При использовании функции mysql_query, она буферизирует результат, вы работаете с курсором данных, которые обработаны и сохранены в память скрипта PHP, естественно при большом обьеме данных, обычного размера памяти выделяемого под скрипт не хватит. Это называется буферизированный запрос.
На помощь приходит функция mysql_unbuffered_query, она не сохраняет результат выполнения в память, а выполняет перемещение курсора в базе данных, благодаря чему память скрипта не засоряется. Это называется небуферизированный запрос.
Тоесть в случае mysql_query вы работате с курсором из памяти PHP, а во втором случае с курсором базы данных. Меняйте mysql_query на mysql_unbuffered_query и все будет отлично.
Хочу заметить, что расширение mysql устарело и его использование небезопасно, как минимум из-за отсутствия функций привязки параметров, и отсуствия поддержки в PHP 5.5 и выше, воспользуйтесь библиотекой mysqli или PDO, последняя предоставляет более удобный обьектно-ориентированный доступ к данным.
У небуферизированных запросов есть преимущества и недостатки:
Преимущества:
Недостатки:
Небуферизированный запрос на PDO выглядит вот так:
<?php
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$uresult = $pdo->query("SELECT Name FROM City");
if ($uresult) {
while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) {
echo $row['Name'] . PHP_EOL;
}
}
?>
На официальном сайте PHP есть информация по буфферизированным и небуферизированным запросом на английском языке.
P.S Если вам нужен только ID выбирайте в запросе только id, а не все поля из таблицы
Чтобы оптимизировать работу с памятью при задаче обхода большой таблицы, выбирайте не всю таблицу, а только колонку с первичным ключом из неё:
/*Обход большой таблицы с экономией памяти*/
$query = mysql_query('SELECT id FROM `table`;');
while ($id = mysql_fetch_array($query)[0])
{
$row = mysql_fetch_array( mysql_query('SELECT * FROM `table` where id = '.$id.';') );
/* Делаем что-то с полными данными ряда таблицы $row */
...
}
Внутри цикла, если того требует задача - выберите полные данные по ряду, зная id. В таком случае каждый шаг цикла, память, захваченная переменной $row
- отправится в garbage collector, т.е. освободится при необходимости.
Кстати это догма при написании скриптов портирования на PHP. Догма эта правда относится к построителям запросов - которые не различают query и fetch в общем случае для упрощения работы с БД.
Замечу, что драйвер mysql и уязвим, о чём написано на каждой странице php.net, ему посвящённой. Необходимо использовать PDO
, Doctrine DBAL
, или на худой конец mysqli
.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как можно сделать ввод текста с возможностью форматирования (жирный/курсив/цветной итд
Собственно есть рамка в фотошопе, но как сверстать - не знаюПолучается криво