Использование памяти фасада Laravel dabatabse

#php #laravel #memory #pdo

#php #laravel #память #pdo

Вопрос:

Я нашел отличный пример, написанный на php pdo, который помогает перебирать огромное количество данных, фактически не выделяя память для всего набора результатов:

     $sql = 'SELECT * from playlists limit 50000';
    $statement = $pdo->prepare($sql);
    $statement->execute();

    while (($result = $statement->fetch(PDO::FETCH_ASSOC)) !== false) {
        //do something
    }
  

Я провел исследование, и этот подход использует 18mb объем памяти.

Если я получу все результаты, подобные этому, $results = $statement->fetchAll(PDO::FETCH_ASSOC); использование памяти увеличится до 35mb .

Использование illuminate/database компонента laravel и очень похожего подхода DB::table('playlists')->limit(50000)->get(); также использует 35mb объем памяти.

  • Как я могу достичь первого подхода, используя Laravel eloquent или фасад DB?
  • Не могли бы вы предложить несколько статей о том, как развивается эта разница в использовании памяти?

Спасибо

Комментарии:

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

Ответ №1:

Когда вы выполняете SQL-запрос с помощью php (либо функций mysql, либо PDO), все данные, возвращенные из запроса, загружаются в память в виде «набора результатов».

Чтобы использовать данные в «наборе результатов», вы должны извлекать их из обычных php-массивов / объектов.

PDOStatement::fetch — извлекает одну строку из результирующего набора в память.

PDOStatement::fetchAll — извлекает все строки из результирующего набора в память, тем самым удваивая использование памяти.

Eloquent обладает способностью разбивать на части результирующие наборы. Это эквивалентно выполнению «X-кратной выборки» в PDO.

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

Комментарии:

1. Допустим, я увеличил объем памяти на 100. Таким образом, при выполнении каждого фрагмента будет выделяться память для 100 строк или только для одной?

2. @EvaldasButkus Каждое выполнение фрагмента загружает в память 100 строк одновременно. Во втором фрагменте первый фрагмент переопределяется вторым фрагментом. Таким образом, теоретически максимальное использование памяти должно составлять результирующий набор размер блока.

Ответ №2:

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

 DB::table('playlists')->chunk(1000, function($playlists) use($count) {
    foreach($playlists as $playlist) {
        // do something with this playlist
    }
});
  

Это гарантирует, что в оперативную память одновременно загружается не более размера блока (в моем примере 1000 строк). 1 кб является произвольным; вы могли бы разделить 1, 100, 253 и т.д.

Комментарии:

1. Если вы хотите ограничить ее максимум 50 тысячами строк, вам нужно будет выполнить небольшую логику, чтобы отслеживать итерации в цикле.