Processamento de grandes dados em PHP: do mito ao projeto real

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

PHP e Big Data: não é um oxímoro, mas uma realidade



Quando se ouve "processamento de grandes dados", a primeira coisa que vem à mente é Spark, Hadoop ou Python com Pandas. PHP nesta lista geralmente é percebido como "uma linguagem para landing pages e fóruns". Mas vamos encarar a verdade: se o seu projeto já vive em PHP, reescrevê-lo inteiramente em Go para uma única tarefa de processamento de um CSV de gigabytes é usar um canhão para matar uma mosca.



PHP lida muito bem com Big Data, se você abordar a questão com inteligência. Neste artigo, vamos analisar técnicas reais: como não matar o servidor ao trabalhar com arquivos de 10+ GB, como processar milhões de linhas de um banco de dados sem out of memory, e como transformar PHP em um verdadeiro pipeline de dados. Sem enrolação, apenas código e soluções arquiteturais.



Por que o PHP "não gosta" de grandes dados (e como corrigir isso)



O principal problema do PHP no contexto de Big Data é seu modelo de execução. O script é executado sequencialmente, carregando tudo na memória. Tente usar file_get_contents() em um arquivo de 5 GB — o servidor simplesmente cairá.



Mas há uma boa notícia: o PHP possui mecanismos embutidos para processamento em fluxo. Basta esquecer os métodos "bárbaros" como file() ou file_get_contents() e migrar para geradores, fluxos e consultas em chunk.



Geradores: sua principal ferramenta



Os geradores (palavra-chave yield) permitem retornar dados um elemento de cada vez, sem carregar todo o conjunto na memória. Isso é ideal para ler arquivos grandes ou consultas de banco de dados.



Exemplo: lendo um arquivo CSV de 5 GB linha por linha, sem matar a memória:



<?phpfunction readLargeCSV(string $filePath): Generator{    $handle = fopen($filePath, 'r');    if ($handle === false) {        throw new RuntimeException("Não foi possível abrir o arquivo: $filePath");    }

// Pula o BOM, se houver $bom = fread($handle, 3); if ($bom !== "\\xEF\\xBB\\xBF") { rewind($handle); // Se não houver BOM, volta ao início }

while (($row = fgetcsv($handle, 0, ',')) !== false) { yield $row; }

fclose($handle);}

// Usoforeach (readLargeCSV('/data/orders_2024.csv') as $index => $row) { // Processa cada linha uma por uma if ($index === 0) { continue; // pula o cabeçalho } processOrder($row);}?>


Por que isso funciona? O gerador não carrega o arquivo inteiro em um array. Ele lê uma linha — entrega — lê a próxima. O consumo de memória permanece na faixa de alguns kilobytes, independentemente do tamanho do arquivo.



Trabalhando com grandes bancos de dados: Consultas em Chunk



Se você precisa processar 5 milhões de registros do MySQL, não tente fazer SELECT * FROM table — isso matará tanto o banco de dados quanto o PHP. Em vez disso, use cursores ou consultas em chunk.



Aqui está a abordagem correta usando PDO e iteração em chunk:



<?phpfunction processLargeTable(PDO $pdo, int $chunkSize = 1000, callable $callback): void{    $offset = 0;    $lastId = 0;

// Usa ORDER BY id para estabilidade $stmt = $pdo->prepare("SELECT * FROM orders WHERE id > :lastId ORDER BY id LIMIT :limit");

do { $stmt->execute(['lastId' => $lastId, 'limit' => $chunkSize]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

if (empty($rows)) { break; }

foreach ($rows as $row) { $callback($row); $lastId = $row['id']; // Lembra o último ID processado }

// Libera a memória unset($rows); $stmt->closeCursor();

} while (true);}

// Uso$pdo = new PDO('mysql:host=localhost;dbname=big_data', 'user', 'pass');$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

p

Blogs

Book Recommendations