В PHP, что происходит в памяти, когда мы используем mysql_query - PullRequest
12 голосов
/ 31 августа 2011

Я использовал для извлечения большого количества данных, используя mysql_query, затем перебирая результаты один за другим для обработки данных.Пример:

$mysql_result = mysql_query("select * from user");
while($row = mysql_fetch_array($mysql_result)){
    echo $row['email'] . "\n";
}

Недавно я рассмотрел несколько фреймворков и понял, что они извлекают все данные в массив в памяти и возвращают массив.

$large_array = $db->fetchAll("select * from user");
foreach($large_array as $user){
    echo $user['email'] . "\n";
}

Я хотел бы знатьплюсы / минусы каждого метода.Мне кажется, что загрузка всего в память - это путь к катастрофе, если у вас очень длинный список предметов.Но опять же, коллега сказал мне, что драйвер mysql все равно должен будет поместить набор результатов в память.Я хотел бы узнать мнение кого-то, кто понимает, что вопрос касается производительности.Пожалуйста, не комментируйте код, я просто сделал его в качестве примера для сообщения.

Спасибо

Ответы [ 4 ]

4 голосов
/ 31 августа 2011

вы смешиваете вещи.

  • удобство использования, которое делает ваш код более плавным с массивами
  • и неоптимизированный алгоритм, когда неопытный программист склонен загружать ВСЕ данные в скрипт вместо создания базы данных для выполнения всех вычислений или получения данных порциями.

Итак. Фреймворки не получают все данные. Они получают только то, что написал программист.
Таким образом, хороший программист не будет загружать большие массивы данных в массив. В тех немногих случаях, когда это действительно необходимо, можно использовать старое построчное извлечение (и каждый фреймворк предоставляет метод для этого). Во всех остальных случаях следует использовать плавное извлечение из массива.

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

2 голосов
/ 31 августа 2011

При работе с большими наборами результатов я обычно выполняю пакеты, например:

$current = 0;
$batchSize = 1000;

while (true) {
  $large_array = $db->fetchAll(sprintf("select * from user limit %s, %s", $current, $batchSize));
  if (sizeof($large_array) == 0) {
    break;
  }

  $current += sizeof($large_array);
  foreach($large_array as $user){
    echo $user['email'] . "\n";
  } 
}

Пока ваш код не пропускает память, вам не придется беспокоиться о том, какой метод используетбольше памятиС точки зрения производительности загрузка всего набора результатов в одном запросе, вероятно, происходит быстрее, хотя вы, вероятно, очень скоро достигнете предела памяти, поэтому производительность больше не является вашей проблемой.

Кстати, это относительно легко проверить самостоятельно, настроив скрипт, который измеряет время (и пиковую память) обоих фрагментов.Держу пари, они не будут сильно отличаться во времени.

1 голос
/ 31 августа 2011

Это правда, что библиотека MySQL "нормально" выбирает все данные в памяти клиента.Обычно это делается с помощью mysql_store_result().Вы можете разделить слишком большие запросы, как показано выше, с помощью ключевого слова LIMIT, но существует риск того, что данные станут противоречивыми, поскольку они могут меняться между ними.Вы можете позаботиться об этом, используя блокировки.

Другой подход может заключаться в использовании mysql_use_result(), который использует больше ресурсов на стороне сервера и требует выполнения задания извлечения как можно скорее.

0 голосов
/ 31 августа 2011

Просто то, что я узнал, когда дело доходит до производительности: foreach быстрее, чем while цикл.Возможно, вам следует сравнить результаты каждого из них и посмотреть, какой из них быстрее и требует меньше памяти.ИМХО, мне больше нравится последний подход.Но вам действительно нужен каждый столбец в пользовательской таблице?Если нет, то просто определите нужные столбцы вместо использования *, чтобы захватить их все.Так как это также поможет с памятью и скоростью.

...