Beliebiges INSERT ... SELECT ...
-Abfrage erwirbt eine SHARED-Sperre
in den Zeilen, die aus der Quelltabelle in SELECT gelesen werden. Aber durch die Verarbeitung kleinerer Zeilenblöcke dauert die Sperre nicht allzu lange.
Die Abfrage mit LIMIT ... OFFSET
wird langsamer und langsamer, je weiter Sie durch die Quelltabelle vorrücken. Bei 10.000 Zeilen pro Block müssen Sie diese Abfrage 10.000 Mal ausführen, jeder muss von vorne beginnen und die Tabelle durchsuchen, um den neuen OFFSET zu erreichen.
Egal, was Sie tun, das Kopieren von 100 Millionen Zeilen wird eine Weile dauern. Es macht eine Menge Arbeit.
Ich würde pt-archiver verwenden , ein kostenloses Tool, das für diesen Zweck entwickelt wurde. Es verarbeitet die Zeilen in "Blöcken" (oder Teilmengen). Die Größe der Chunks wird dynamisch angepasst, sodass jeder Chunk 0,5 Sekunden dauert.
Der größte Unterschied zwischen Ihrer Methode und pt-archiver besteht darin, dass pt-archiver LIMIT ... OFFSET
nicht verwendet , geht es den Primärschlüsselindex entlang und wählt Zeilenabschnitte nach Wert statt nach Position aus. So wird jeder Chunk effizienter gelesen.
Zu Ihrem Kommentar:
Ich gehe davon aus, dass eine Verkleinerung der Stapelgröße – und eine Erhöhung der Anzahl der Iterationen – das Leistungsproblem schlimmer machen wird , nicht besser.
Der Grund dafür ist, dass Sie LIMIT
verwenden mit OFFSET
, muss jede Abfrage am Anfang der Tabelle beginnen und die Zeilen bis zum OFFSET
zählen Wert. Dies wird immer länger, wenn Sie die Tabelle durchlaufen.
Ausführen von 20.000 teuren Abfragen mit OFFSET
dauert länger als die Ausführung von 10.000 ähnlichen Abfragen. Der teuerste Teil besteht nicht darin, 5.000 oder 10.000 Zeilen zu lesen oder sie in die Zieltabelle einzufügen. Der teure Teil besteht darin, immer und immer wieder ~50.000.000 Zeilen zu überspringen.
Stattdessen sollten Sie die Tabelle nach Werten durchlaufen nicht durch Offsets.
INSERT IGNORE INTO Table2(id, field2, field3)
SELECT f1, f2, f3
FROM Table1
WHERE id BETWEEN rowOffset AND rowOffset+limitSize;
Fragen Sie vor der Schleife MIN(id) und MAX(id) ab und starten Sie rowOffset
beim Min-Wert und Schleife bis zum Max-Wert.
So funktioniert pt-archiver.