2017-09-26 2 views
0

Kann ich dieselbe Spalte aktualisieren, die ich für einen Join verwende? Es scheint, als könnte ich das, aber mein Skript stürzt ab, wenn ich es tue.MySQL Ein JOIN ON-Feld ist gültig oder nicht? "JOIN ON a = b SET a = c"

Hintergrund: Ich habe eine alte Datenbank, die ich migriere. Ich verarbeite es durch eine Menge MySQL-Abfragen, die in einer PHP-Schleife laufen. Die Schleifenarbeiter sind großartig, die jeweils 0,5 bis 1 MB Speicher abfragen, um sie zu verarbeiten. Bis es trifft diese Abfrage und plötzlich nimmt es 101% von was auch immer Speicher ich PHP zugewiesen haben:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.category = t2.newcategory 
WHERE t1.category <> ''; 

Wenn memory_limit auf 128M geworfen gesetzt wurde der Fehler war:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted 
(tried to allocate 12288 bytes) 

Als ich das memory_limit gestoßen der Fehler 256M ist:

PHP Fatal error: Allowed memory size of 268435456 bytes exhausted 
(tried to allocate 32768 bytes) 

Aber gerade diese ähnliche Abfrage läuft ganz gut:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.series = t2.series_term 
WHERE t1.category <> '' AND t2.newcategory <> ''; 

PHP-Code auf Anfrage:

$queries = array (
// dozens of MySQL queries here, like this: 
["Count users", 
"SELECT id from $s2.$usr;" 
], 
) 

foreach ($queries as $query){ 
    $mtime = time(); 
    $result = mysqli_query($link, $query[1]); 
    $mem = number_format((memory_get_usage()/1024/10124),2); 
    $mtime = time() - $mtime; 
    $mtime = gmdate("i:s", $mtime); 

    if ($result) { 
    $rows = number_format(mysqli_affected_rows($link)); 
    echo "<tr><td>$mtime</td><td>$rows</td><td>$query[0] — $mem Mb</td></tr>"; 
    } else { 
    $rows = mysqli_error($link); 
    echo "<tr><td>X</td><td>X</td><td>".$query[0]."<br><span style='color:red;'>".$rows."</span></td></tr>"; 
    } 
} 

Gibt es etwas, illegal oder rekursive über SET auf der gleichen Säule verwendet unter Verwendung für ON?

UPDATE:

ich nur zwei kleine Testtabellen erstellt und lief erfolgreich diese Abfrage:

# works 
UPDATE table1 t1 
    JOIN table2 t2 
    ON t1.column1 = t2.column1 
SET t1.column1 = t2.column2 
WHERE t1.column1 <> ''; 

UPDATE 2:

Ich bearbeitete die WHERE-Klausel und jetzt läuft es richtig. 19 Sekunden unter Verwendung von 0,04 MB Speicher:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.category = t2.newcategory 
WHERE t1.category <> '' AND t1.category <> t2.newcategory; 
+0

Bitte auch PHP-Code anzeigen, sehen Sie möglicherweise 'memory_limit' in' php.ini' gesetzt –

+0

Statt ein tun Update mit der gesamten Datenbank, können Sie es nicht in Chunks zum Beispiel für jedes 50.000 Update anstelle von Update-Abfragen auf einmal setzen. – rahul

+0

Akshay Hegde, mein PHP-Limit ist auf 256M eingestellt, angehoben von 128M nach dem ersten Fehler. – Slam

Antwort

0
Ich denke der folgende Code wird auch gut funktionieren! ** Hier Codes: ** UPDATE a.t1 INNER JOIN T2 ON t1.category = t2.oldcategory # SET t1.series = t2.series_term ## mit aus SET WHERE t1.category '' UND t2.newcategory ''; ** UND t2.newcategory '' ** desto mehr Bedingung lassen Sie es arbeiten. Ich denke, es ist mehr Bedingung lassen Sie es funktioniert wegen mehr Bedingung mehr Daten filtern und MySQL weniger Speicher verwenden lassen.

sorry, nur den Code lesen, können Sie keine Daten auf dem Join-Bedingung gesetzt, werden Sie in Endlosschleife

+0

Aber in Ihrem Code wird nichts gesetzt. Ich muss t1.category mit neuen Werten aktualisieren. – Slam

+0

hast du meine Antworten verstanden? Wenn Sie t1.category aktualisieren möchten, sollten Sie mehr Bedingung hinzufügen oder memory_limit erhöhen – Carson

+0

Ich schrieb, dass ich bereits das Limit erhöht. Diese Abfrage verwendet 101% des gesamten Speichers, unabhängig davon, wie groß ich das Limit festlege. Es verwendete 257M, als die sehr ähnliche Abfrage nach ihm nur 0.5M verwendete. Und t2.newcategory hat keine leeren Zeilen. – Slam

0

Nein, Sie können t update same columns which are used in join statement. Think about the logic. It updates one row and it has to recheck the value again since it s unter Verwendung derselben Spalte verbunden. Dies wird zu einer endlosen Rekursion, die Sie zu einer Ausnahme wegen zu wenig Speicher führt.

Warum nicht zuerst IDs speichern, die aktualisiert werden müssen, und Werte im Schlüsselwertfeld. Dann eine Schleife laufen lassen und separat aktualisieren?

SELECT t1.id,t2.newcategory from t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 

betreiben eine foreach Schleife für die Ergebnisliste und aktualisieren jede Zeile

foreach($queryResul as $row){ 
UPDATE t1 SET t1.category = $row->newcategory where t1.id = $row->id; } 
+0

Warum sollte der Wert erneut überprüft werden? Ich nehme an, dass die Reihenfolge der Operationen das JOIN ... ON zuerst ausführt, eine große Tabelle erstellt und dann die Zeilen durchsucht, die das SET ausführen. Ist das falsch? – Slam

+0

Ich weiß nicht, was ein Schlüsselwert-Array ist. Können Sie Code vorschlagen? – Slam

+0

"Erneut überprüfen" oder Re-run die Schleife ist endlose Rekursion zu verhindern überprüfen Sie die aktualisierte Antwort – BRjava

Verwandte Themen