Regelmäßig große Mengen (4 Millionen Zeilen) von MySQL-Daten effizient löschen

10

Wir haben eine MySQL-Tabelle, die zu jedem Zeitpunkt ungefähr 12 Millionen Zeilen enthält. Wir müssen alte Daten löschen, um die Größe der Tabelle etwas überschaubar zu halten.

Im Moment führen wir diese Abfrage täglich um Mitternacht mit einem Cron-Job aus:

DELETE FROM table WHERE endTime < '1393632001'

Das letzte Mal, als die Abfrage ausgeführt wurde, wurden 4.602.400 untersucht, es dauerte über 3 Minuten und die CPU ging durch das Dach.

CPU-Spitzen um Mitternacht

Was können wir tun, um zu verhindern, dass die CPU, die synchronen Datenbankverbindungen, die Festplatten-Cue-Tiefe usw. unangemessen ansteigen, während alte Daten gelöscht werden?

PS: Sie werden feststellen, dass die Abfrage tatsächlich zu einem ziemlich ungünstigen Zeitpunkt in unserem Nutzungszyklus stattfindet. Angenommen, wir haben das Timing der Abfrage bereits so verschoben, dass es jeden Tag am niedrigsten Verwendungspunkt auftritt. Außerdem gibt es keinen Index für "endTime" und ich würde es vorziehen, wenn möglich so zu bleiben, da eine Menge Daten sehr regelmäßig eingefügt werden und nicht viel nachgeschlagen wird.


quelle
Vielleicht verwenden Sie Cron-Jobs, um alle 10 Minuten und 100.000 pro Runde oder alle 5 Minuten 50.000 pro Runde zu löschen
kleinere Stücke regelmäßig?
ok, aber es scheint so, als ob dies unsere Benutzererfahrung für längere Zeiträume beeinträchtigen könnte :) Was können wir in Bezug auf Abfragen / Design tun?
1
186k Benutzer, kein engagierter DB-Typ?
1
Sie erhalten bessere Antworten auf "Datenbankadministratoren"
James Anderson

Antworten:

13

Die Lösung für Ihr Problem ist eine MySQL-Funktion namens "Partitionierung". Die Dokumentation finden Sie hier .

Bei der Partitionierung wird eine einzelne Tabelle in separaten "Partitionen" gespeichert. Diese werden durch einen bestimmten Ausdruck definiert, normalerweise einen Spaltenwert oder einen Bereich. In Ihrem Fall würde dies wahrscheinlich darauf beruhen endTime- vorausgesetzt, es ist bekannt, wann ein Datensatz erstellt wird und es ändert sich nicht.

Sie würden den Wert eines Tages endTimein jeder Partition speichern . Dann würde der Löschschritt darin bestehen, eine Partition abzuschneiden, anstatt eine Reihe von Zeilen in einer großen Tabelle zu löschen. Das Abschneiden der Partition wäre eine viel schnellere Methode.

Gordon Linoff
quelle
Wow, das war unglaublich hilfreich und scheint eine perfekte Lösung zu sein. Zeit, sich über die Partitionierung zu informieren! Vielen Dank!
Partitionierung ist zwar eine gute Lösung, aber Vorsicht vor Overhead - sie kann Ihre Abfragen erheblich verlangsamen. Außerdem ist das Abschneiden der Tabelle auch nicht sofort möglich. Ich würde pt-archiver in Betracht ziehen. Sie können Ihre Probleme mit Spikes lösen und Ihren Tisch so einfach wie jetzt halten
akuzminsky