2014-01-07 3 views
1

Я извлечения 10K записей (имеющих 10 столбцов с типами данных, как datetime, text, int, varchar) с использованием mysql_fetch_object и загрузки всех столбцов из каждой присоединяемой таблицы в запросе, который дал память но затем я изменил запрос, чтобы получить только некоторые конкретные столбцы, которые устранили ошибку, избавив меня от утопления в озере ошибок.Как предотвратить фатальную ошибку размера памяти истощения

Запрос просто присоединение 3 таблицы, A, B, C, как, SELECT * FROM A JOIN B ON ......JOIN C ON ...... WHERE.....

Но я до сих пор в страхе, что если нет. записей или нет. столбцов, то ошибка снова появится .... так что будет полным решением этого? Я прочитал другие сообщения о SO и обнаружил, что следует использовать mysql_unbuffered_query. Но нет ли решения, если я использую mysql_fetch_object? Кроме того, небуферизованный запрос занимает больше времени, поскольку он возвращает одну строку за раз?

+0

Вы можете дать нам ** фактический ** код? если вы хотите его оптимизировать, нам нужно что-то оптимизировать. Кстати, это может быть лучше на codereview.stackexchange.com. – PlantTheIdea

+0

показать фактический запрос. Вы можете очень хорошо производить декартовое соединение, поэтому ваш 10k записывает воздушный шар в миллиарды или триллионы строк. –

+0

no я выполнил запрос в mysql, и он буквально вернул 10000 строк. – sqlchild

ответ

2

MySQL не тот, который исчерпывает память здесь, это ваш PHP-скрипт, поэтому уменьшение размера SELECT является лишь частичным решением.

Я думаю, что вы делаете что-то вроде:

$collect = array(); 
while (has_records) { 
    $collect[] = fetch_record; 
} 
foreach ($collect as $row) { 
    handle_record($row); 
} 

Конечно $collect получит очень большой. Посмотрите, можете ли вы избежать сбора всех записей: прочитайте запись, обработайте ее, очистите память и выполните следующую итерацию.

while (has_records) { 
    var $row = fetch_record(); 
    handle_record($row); 
} 

Итератор пример кода:

class DB { 
    function get_iterator($query) { 
     $query_result = do_query($query); 
     return new Iterator($query_result); 
    } 
} 

class MyIterator { 
    public function __construct($mysql_result) { 
     $this->res = $mysql_result; 
    } 
    public function hasMore() { 
     // do some counting 
    } 
    public function fetch() { 
     return mysql_fetch($this->res); 
    } 
} 

echo '<table>'; 
$it = $db->get_iterator("SELECT * FROM `items`"); 
while($it->hasMore()) { 
    echo '<tr>'; 
    $row = $it->fetch(); 
    foreach ($row as $cell) { 
     echo '<td>' . $cell . '</td>'; 
    } 
    echo '</tr>'; 
} 
echo '</table>'; 

Вы можете даже implements Iterator, так что вы можете foreach над $it непосредственно, который является удивительным.

+0

да, вы абсолютно правы, я использую метод, который вы опубликовали – sqlchild

+0

Хорошо, это поможет вам решить проблему? – Halcyon

+0

Это на самом деле хорошая идея. Вы также можете разделить запросы, чтобы делать их в партиях, скажем по 1 к каждому. –

Смежные вопросы