Die Geschichte des physischen Löschens von 300 Millionen Datensätzen in MySQL

Einführung



Hallo. Ich bin ningenMe, ein Webentwickler.



Wie der Titel schon sagt, geht es in meiner Geschichte darum, 300 Millionen Datensätze in MySQL physisch zu löschen.



Ich interessierte mich dafür und beschloss, ein Memo (eine Anweisung) zu machen.



Start - Alarm



Der Batch-Server, den ich verwende und pflege, hat einen regelmäßigen Prozess, der einmal täglich Daten für den letzten Monat von MySQL sammelt.



Normalerweise wird dieser Vorgang in ungefähr 1 Stunde abgeschlossen, aber diesmal wurde er 7 oder 8 Stunden lang nicht abgeschlossen, und die Warnung hörte nicht auf zu kriechen ...



Suche nach einem Grund



Ich habe versucht, den Prozess neu zu starten, mir die Protokolle anzusehen, aber nichts Schreckliches gesehen.

Die Anfrage wurde korrekt indiziert. Aber als ich mich fragte, was falsch lief, stellte ich fest, dass die Datenbank ziemlich groß ist.



hoge_table | 350'000'000 |


350 Millionen Datensätze. Die Indizierung scheint korrekt zu funktionieren, nur sehr langsam.



Die erforderliche Datenerfassung pro Monat betrug etwa 12.000.000 Datensätze. Es sieht so aus, als hätte der Befehl select lange gedauert und die Transaktion wurde lange nicht ausgeführt.



DB



Grundsätzlich handelt es sich um eine Tabelle, die täglich um etwa 400.000 Datensätze wächst. Die Datenbank sollte nur Daten für den letzten Monat sammeln, daher wurde berechnet, dass sie genau dieser Datenmenge standhält, aber leider wurde der Drehvorgang nicht berücksichtigt.



Diese Datenbank wurde nicht von mir entwickelt. Ich habe es von einem anderen Entwickler übernommen, also fühlte es sich wie eine technische Schuld an.



Der Moment kam, als die täglich eingefügte Datenmenge groß wurde und schließlich an ihre Grenzen stieß. Es wird davon ausgegangen, dass bei der Arbeit mit einer so großen Datenmenge eine Trennung erforderlich wäre, dies wurde jedoch leider nicht durchgeführt.



Und dann trat ich ein.



Korrektur



Es war rationaler, die Datenbank selbst und die Zeit für ihre Verarbeitung zu reduzieren, als die Logik selbst zu ändern.



Die Situation sollte sich erheblich ändern, wenn 300 Millionen Datensätze gelöscht werden, also habe ich mich dazu entschlossen ... Eh, ich dachte, es würde definitiv funktionieren.



Schritt 1



Nachdem ich ein zuverlässiges Backup vorbereitet hatte, begann ich endlich, Anfragen zu senden.



「Anfrage senden」



DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';


「...」



「...」



“Hmm… Keine Antwort. Vielleicht dauert der Prozess lange? " - Ich dachte, aber nur für den Fall, dass ich in grafana schaute und sah, dass die Festplattenlast sehr schnell wuchs.

"Gefährlich" - dachte ich noch einmal und stoppte sofort die Anfrage.



Schritt 2



Nachdem ich alles analysiert hatte, stellte ich fest, dass die Datenmenge zu groß war, um alles auf einmal zu löschen.



Ich beschloss, ein Skript zu schreiben, mit dem etwa 1.000.000 Datensätze gelöscht werden konnten, und führte es aus.



「Ich implementiere das Skript」



"Jetzt wird es definitiv funktionieren", dachte ich



Schritt 3



Die zweite Methode funktionierte, erwies sich jedoch als sehr zeitaufwändig.

Um alles ordentlich und ohne zusätzliche Nerven zu machen, würde es ungefähr zwei Wochen dauern. Trotzdem entsprach dieses Szenario nicht den Serviceanforderungen, sodass ich mich davon entfernen musste.



Deshalb habe ich mich für Folgendes entschieden:



Kopieren Sie die Tabelle und benennen Sie sie um



Im vorherigen Schritt wurde mir klar, dass das Löschen einer so großen Datenmenge eine ebenso große Last verursacht. Aus diesem Grund habe ich beschlossen, mithilfe von Einfügen eine neue Tabelle von Grund auf neu zu erstellen und die Daten, die ich löschen wollte, in diese Tabelle zu verschieben.



| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|


Wenn Sie die neue Tabelle auf die gleiche Größe wie oben einstellen, sollte auch die Verarbeitungsgeschwindigkeit um 1/7 schneller werden.



Nachdem ich die Tabelle erstellt und umbenannt hatte, begann ich, sie als Mastertabelle zu verwenden. Wenn ich jetzt eine Tabelle mit 300 Millionen Datensätzen ablege, sollte alles in Ordnung sein.

Ich fand heraus, dass das Abschneiden oder Löschen weniger Aufwand bedeutet als das Löschen, und entschied mich für diese Methode.



Performance



「Anfrage senden」



INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';


「...」

「...」

uh uh ...? 」



Schritt 4



Dachte, die vorherige Idee würde funktionieren, aber nach dem Absenden der Einfüge-Anfrage traten mehrere Fehler auf. MySQL spart nicht.



Ich war schon so müde, dass ich anfing zu denken, dass ich das nicht mehr tun wollte.



Ich saß da ​​und dachte nach und stellte fest, dass es vielleicht zu viele Einfügeanfragen für eine Zeit gab ...

Ich habe versucht, eine Einfügeanforderung für die Datenmenge zu senden, die die Datenbank in einem Tag verarbeiten sollte. Passierte!



Nun, danach senden wir weiterhin Anfragen für die gleiche Datenmenge. Da wir die monatliche Datenmenge entfernen müssen, wiederholen wir diesen Vorgang etwa 35 Mal.



Tabelle umbenennen



Hier war das Glück auf meiner Seite: alles verlief reibungslos.



Alarm weg



Die Stapelverarbeitungsgeschwindigkeit wurde erhöht.



Früher dauerte dieser Vorgang ungefähr eine Stunde, jetzt dauert er ungefähr 2 Minuten.



Nachdem ich überzeugt war, dass alle Probleme gelöst waren, ließ ich 300 Millionen Datensätze fallen. Ich löschte den Tisch und fühlte mich wiedergeboren.



Zusammenfassen



Ich erkannte, dass die Rotationsverarbeitung bei der Stapelverarbeitung übersehen wurde und das war das Hauptproblem. Ein solcher Fehler in der Architektur ist Zeitverschwendung.



Denken Sie über das Laden der Datenreplikation nach, indem Sie Datensätze aus der Datenbank löschen? Lassen Sie uns MySQL nicht überladen.



Diejenigen, die sich mit Datenbanken auskennen, werden mit einem solchen Problem definitiv nicht konfrontiert sein. Im Übrigen hoffe ich, dass dieser Artikel hilfreich war.



Danke fürs Lesen!



Wir würden uns sehr freuen, wenn Sie uns mitteilen, ob Ihnen dieser Artikel gefallen hat. War die Übersetzung klar, war sie für Sie nützlich?



All Articles