Dowolny INSERT ... SELECT ...
zapytanie uzyska blokadę SHARED
w wierszach, które odczytuje z tabeli źródłowej w SELECT. Ale przetwarzając mniejsze fragmenty wierszy, blokada nie trwa zbyt długo.
Zapytanie z LIMIT ... OFFSET
będzie wolniej i wolniej w miarę przechodzenia przez tabelę źródłową. Przy 10 000 wierszy na porcję, musisz uruchomić to zapytanie 10 000 razy, każde z nich musi zacząć od nowa i przeskanować tabelę, aby osiągnąć nowe PRZESUNIĘCIE.
Bez względu na to, co zrobisz, skopiowanie 100 milionów wierszy zajmie trochę czasu. Robi dużo pracy.
Używałbym pt-archiver , darmowe narzędzie przeznaczone do tego celu. Przetwarza wiersze w „kawałkach” (lub podzbiorach). Dynamicznie dostosuje rozmiar porcji, tak aby każda porcja trwała 0,5 sekundy.
Największą różnicą między twoją metodą a pt-archiver jest to, że pt-archiver nie używa LIMIT ... OFFSET
, przechodzi wzdłuż indeksu klucza podstawowego, wybierając fragmenty wiersza według wartości zamiast według pozycji. Dzięki temu każdy fragment jest czytany wydajniej.
Odpowiedz na swój komentarz:
Spodziewam się, że zmniejszenie rozmiaru partii — i zwiększenie liczby iteracji — spowoduje, że problem z wydajnością pogorszy się , nie lepiej.
Powodem jest to, że gdy używasz LIMIT
z OFFSET
, każde zapytanie musi zaczynać się od początku tabeli i liczyć wiersze aż do OFFSET
wartość. To staje się coraz dłuższe, gdy przechodzisz przez tabelę.
Uruchamianie 20 000 kosztownych zapytań przy użyciu OFFSET
zajmie więcej czasu niż uruchomienie 10 000 podobnych zapytań. Najdroższą częścią nie będzie odczytywanie 5 000 lub 10 000 wierszy ani wstawianie ich do tabeli docelowej. Kosztowna część będzie przeskakiwać przez ~50 000 000 wierszy w kółko.
Zamiast tego powinieneś iterować po tabeli według wartości nie przez przesunięcia.
INSERT IGNORE INTO Table2(id, field2, field3)
SELECT f1, f2, f3
FROM Table1
WHERE id BETWEEN rowOffset AND rowOffset+limitSize;
Przed pętlą zapytaj o MIN(id) i MAX(id) i uruchom rowOffset
przy minimalnej wartości i zapętlaj do maksymalnej wartości.
Tak działa pt-archiver.