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