2016-07-27 3 views
1

У меня есть таблица с ~ 70 тыс. Записей и размером ~ 12 Мбайт (МБ).Почему PHP выделяет гораздо больше памяти, чем нужно?

require_once('connection.php'); 
$sql = "SELECT * FROM BlahBlah"; 
$result = $con->query($sql); 
$data = array(); 
while($row = $result->fetch_assoc()) { 
    $data[] = $row; 
} 
echo json_encode($data); 

Когда я некоторое время FETCH_ASSOC() цикл в PHP для хранения результата и эхо возвращает все строки в таблице в формате Json на JavaScript, я получаю Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes).

Я понимаю, что требуется более 12 Мбайт памяти, но выделение в 10 раз больше памяти по мере необходимости отбрасывает меня. У меня есть еще один запрос до этого, и он захватывает только 151 КБ таблицы.

EDIT: Я прочитал сообщение в блоге ниже, чтобы понять, почему PHP требует столько накладных расходов.

Одно из решений заключается в том, чтобы установить ограничение на неограниченную память, но это похоже на ужасный подход, так как моя база данных растет на ~ 10 тыс. Записей в день. Есть ли другой способ вывода всех строк таблицы из MySQL в Json-формате клиенту? Я создаю маркеры карты google на стороне клиента из полученных строк

+0

Возможный дубликат http://stackoverflow.com/questions/415801/allowed-memory-size-of-33554432-bytes-exhausted-tried-to-allocate-43148176-byte –

+0

его принципиально невозможно определить, какое использование памяти php будет использовать, просто просматривая код –

+2

Попробуйте прочитать [это сообщение в блоге] (https://nikic.github.io/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG .html), который точно определяет, какая память используется для построения массивов в PHP –

ответ

1

У меня была такая же проблема, как и вы. Я решаю это, создавая строку json вручную и отправляя ее пользователю по частям как можно скорее (конечно же, партиями).

require_once('connection.php'); 
$sql = "SELECT * FROM BlahBlah"; 
$result = $con->query($sql); 


$json_str = '['; // we will send this to user. 
$count = 0; // current number of fetched rows. 
$max_count = 100; // max number of rows that we store in memmory bofore sending to client. 

$quote = ''; 
// $quote will be used to concatenate json strings 
// it's empty only on first iteration 

while($row = $result->fetch_assoc()) { 
    $json_str .= $quote . json_encode($row); 
    $quote = ','; 
    $count++; 
    if($count >= $max_count){ 
    echo $json_str; //send all data that we have for now 
    // if you don't want to echo it you can save it to file. 

    $json_str = ''; //clear string (prevent memory growing) 
    $count = 0; 
    } 
} 
echo $json_str .']'; 

UPDATE: Также существуют и другие способы, чтобы уменьшить использование памяти

  1. Вы можете использовать SplFixedArray для $data хранить все строки (в моей практике это было 20-30% эффективнее, чем PHP массив).
  2. Вы можете json закодировать строки, прежде чем добавлять их в $ data. Это смешно, но строки json могут быть более эффективными с точки зрения памяти, чем Array.

Но эти методы менее эффективны и медленнее.