PHP und Big Data: kein Oxymoron, sondern Realität
Wenn man "Verarbeitung großer Datenmengen" hört, denkt man zuerst an Spark, Hadoop oder Python mit Pandas. PHP wird in dieser Liste normalerweise als "Sprache für Landingpages und Foren" wahrgenommen. Aber sehen wir der Wahrheit ins Auge: Wenn Ihr Projekt bereits auf PHP läuft, es komplett für eine einzige Aufgabe zur Verarbeitung einer gigabytegroßen CSV-Datei auf Go umzuschreiben, ist das mit Kanonen auf Spatzen schießen.
PHP kommt mit Big Data hervorragend zurecht, wenn man die Sache mit Bedacht angeht. In diesem Artikel werden wir echte Techniken durchgehen: wie man den Server nicht killt, wenn man mit Dateien von 10+ GB arbeitet, wie man Millionen von Zeilen aus der Datenbank ohne out of memory verarbeitet und wie man PHP in eine echte Datenpipeline verwandelt. Ohne Wasser, nur Code und Architekturentscheidungen.
Warum PHP große Datenmengen "nicht mag" (und wie man das behebt)
Das Hauptproblem von PHP im Kontext von Big Data ist sein Ausführungsmodell. Das Skript wird sequenziell ausgeführt und lädt alles in den Speicher. Versuchen Sie file_get_contents() bei einer 5 GB großen Datei – der Server stürzt einfach ab.
Es gibt aber auch eine gute Nachricht: PHP hat eingebaute Mechanismen für die Streaming-Verarbeitung. Man muss nur die "barbarischen" Methoden wie file() oder file_get_contents() vergessen und auf Generatoren, Streams und Chunk-Abfragen umsteigen.
Generatoren: Ihr wichtigstes Werkzeug
Generatoren (Schlüsselwort yield) ermöglichen es, Daten Element für Element zurückzugeben, ohne den gesamten Satz in den Speicher zu laden. Das ist ideal zum Lesen großer Dateien oder Datenbankabfragen.
Beispiel: Wir lesen eine 5 GB große CSV-Datei zeilenweise, ohne den Speicher zu killen:
<?phpfunction readLargeCSV(string $filePath): Generator{ $handle = fopen($filePath, 'r'); if ($handle === false) { throw new RuntimeException("Datei konnte nicht geöffnet werden: $filePath"); }
// BOM überspringen, falls vorhanden $bom = fread($handle, 3); if ($bom !== "\\xEF\\xBB\\xBF") { rewind($handle); // Wenn kein BOM, zurück zum Anfang }
while (($row = fgetcsv($handle, 0, ',')) !== false) { yield $row; }
fclose($handle);}
// Verwendungforeach (readLargeCSV('/data/orders_2024.csv') as $index => $row) { // Jede Zeile einzeln verarbeiten if ($index === 0) { continue; // Kopfzeile überspringen } processOrder($row);}?>Warum funktioniert das? Der Generator lädt nicht die gesamte Datei in ein Array. Er liest eine Zeile – gibt sie aus – liest die nächste. Der Speicherverbrauch bleibt unabhängig von der Dateigröße auf dem Niveau weniger Kilobyte.
Arbeit mit großen Datenbanken: Chunk-Abfragen
Wenn Sie 5 Millionen Datensätze aus MySQL verarbeiten müssen, versuchen Sie nicht SELECT * FROM table – das killt sowohl die DB als auch PHP. Verwenden Sie stattdessen Cursor oder Chunk-Abfragen.
Hier ist der richtige Ansatz mit PDO und Chunk-Iteration:
<?phpfunction processLargeTable(PDO $pdo, int $chunkSize = 1000, callable $callback): void{ $offset = 0; $lastId = 0;
// ORDER BY id für Stabilität verwenden $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']; // Letzte verarbeitete ID merken }
// Speicher freigeben unset($rows); $stmt->closeCursor();
} while (true);}
// Verwendung$pdo = new PDO('mysql:host=localhost;dbname=big_data', 'user', 'pass');$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
p