PHP에서 대량의 데이터를 반복할 때 메모리 소모 문제를 해결하는 방법

coldplay.xixi
풀어 주다: 2023-04-09 14:42:01
앞으로
3597명이 탐색했습니다.

ㅋㅋㅋ 456바이트가 소진되었습니다

PHP에서 대량의 데이터를 반복할 때 메모리 소모 문제를 해결하는 방법최대 허용 메모리가 소진되었다는 오류 메시지가 표시됩니다. 처음에는 이런 오류가 나서 놀랐지만, 생각해보면 별로 놀라운 일도 아닌데, 제가 개발 중인 프로그램은 40,000개의 레코드가 있는 테이블에서 특정 특성을 갖는 전체 테이블을 검색하는 루프 문을 사용하기 때문입니다. 즉, 한 번에 40,000개의 데이터를 꺼내야 하고, 일일 데이터를 하나씩 확인해야 합니다. 40,000개의 데이터가 모두 메모리에 로드되면 메모리가 터지지 않으면 이상할 것이라고 생각할 수 있습니다.

결국 프로그래밍을 수년간 해오면서 PHP가 데이터를 한꺼번에 로드하지 않는 API를 제공한다는 것을 어렴풋이 기억하고 있습니다. 스트리밍 미디어처럼 사용하고 잃어버릴 수 있는 쿼리 방식이고, 데이터가 메모리에 쌓이지 않습니다. 간단한 검색 끝에 공식 홈페이지에서 정확한 사용법을 찾았습니다. 이 문제는 PHP 공식 웹사이트에서 Buffered 및 Unbuffered 쿼리라고 합니다. PHP의 기본 쿼리 모드는 버퍼링 모드입니다. 즉, 쿼리 데이터 결과는 PHP 프로그램에서 처리하기 위해 한꺼번에 메모리로 추출됩니다. 이는 PHP 프로그램에 행 수 계산, 특정 행에 대한 포인터 지정 등과 같은 추가 기능을 제공합니다. 더 중요한 것은 프로그램이 데이터 세트에 대해 2차 쿼리와 필터링 작업을 반복적으로 수행할 수 있다는 것입니다. 그러나 이 버퍼링된 쿼리 모드의 단점은 메모리를 소비한다는 것, 즉 속도를 위해 공간을 교환한다는 것입니다. 반면에 또 다른 PHP 쿼리 모드는 버퍼링되지 않은 쿼리입니다. 데이터베이스 서버는 데이터를 한 번에 모두 반환하지 않고 하나씩 반환합니다. 결과적으로 PHP 프로그램은 메모리를 덜 소비하지만 데이터베이스에 대한 부담을 증가시킵니다. server. , 데이터베이스는 모든 데이터를 가져올 때까지 PHP가 데이터를 가져올 때까지 기다리기 때문입니다. 분명히 버퍼링된 쿼리 모드는 작은 데이터 볼륨 쿼리에 적합하고, 버퍼링되지 않은 쿼리 모드는 큰 데이터 볼륨 쿼리에 적합합니다. PHP의 버퍼 모드 쿼리는 누구나 알고 있습니다. 아래 예시는 버퍼되지 않은 쿼리 API를 실행하는 방법입니다.

버퍼되지 않은 쿼리 방법 1: mysqli

<?php
$mysqli  = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);

if ($uresult) {
   while ($row = $uresult->fetch_assoc()) {
       echo $row[&#39;Name&#39;] . PHP_EOL;
   }
}
$uresult->close();
?>
로그인 후 복사
버퍼되지 않은 쿼리 방법 2: pdo_mysql

<?php
$pdo = new PDO("mysql:host=localhost;dbname=world", &#39;my_user&#39;, &#39;my_pass&#39;);
$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[&#39;Name&#39;] . PHP_EOL;
   }
}
?>
로그인 후 복사

버퍼되지 않은 쿼리 방법 3: mysql
<?php
$conn = mysql_connect("localhost", "my_user", "my_pass");
$db   = mysql_select_db("world");

$uresult = mysql_unbuffered_query("SELECT Name FROM City");
if ($uresult) {
   while ($row = mysql_fetch_assoc($uresult)) {
       echo $row[&#39;Name&#39;] . PHP_EOL;
   }
}
?>
로그인 후 복사

foreachphp 중국 네티즌들의 불만:

이건 제너레이터

이런 쓰는 방법은 바로 쓸 수 있어요

빅데이터 처리할 때는 저런 식으로 쓰는 건 불가능해요

PHP 중국 네티즌 샤오첸이 올바른 방법을 알려줬어요

<?php

if (!function_exists(&#39;getYieldBigData&#39;)) {
    /**
     * 使用生成器返回生成器对象
     * @param array $data
     * @return Generator
     */
    function getYieldBigData($data = [])
    {
        foreach ($data as $tmp_data) {
            yield $tmp_data;
        }
        unset($tmp_data);
    }
}


if (!function_exists(&#39;foreachBigData&#39;)) {
    /**
     * 循环大量数据使用生成器来制造值
     * @param array $data
     * @return array|false
     */
    function foreachBigData($data = [])
    {
        if (0 == count($data)) {
            return false;
        }
        $tmp = [];
        foreach (getYieldBigData($data) as $v) {
            $tmp[] = $v;
        }
        unset($v);
        return $tmp;
    }
}

//调用方法
/**
 * @var $data array
 */
$data = [];
/**
 * @var $ret array
 */
$ret = foreachBigData($data);

return $ret;
로그인 후 복사

초보자도 이해할 수 있어요 알았어요 !

위와 같이 이 방법을 사용하면 회당 100만개까지 도달할 수 있습니다!

이 기사는 PHP 중국어 웹사이트

php 그래픽 튜토리얼

채널에서 가져온 것입니다. 원저자: God of War Wukong, PHP 중국어 웹사이트 보조 편집자입니다.

위 내용은 PHP에서 대량의 데이터를 반복할 때 메모리 소모 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:webhek.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿