Ich habe also diese Prüftabelle (verfolgt Aktionen für jede Tabelle in meiner Datenbank):
CREATE TABLE `track_table` (
`id` int(16) unsigned NOT NULL,
`userID` smallint(16) unsigned NOT NULL,
`tableName` varchar(255) NOT NULL DEFAULT '',
`tupleID` int(16) unsigned NOT NULL,
`date_insert` datetime NOT NULL,
`action` char(12) NOT NULL DEFAULT '',
`className` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `userID` (`userID`),
KEY `tableID` (`tableName`,`tupleID`,`date_insert`),
KEY `actionDate` (`action`,`date_insert`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
und ich muss anfangen, veraltete Elemente zu archivieren. Die Tabelle ist auf ungefähr 50 Millionen Zeilen angewachsen. Der schnellste Weg, die Zeilen zu löschen, bestand darin, jeweils eine Tabelle (basierend auf tableName
) zu löschen .
Dies funktioniert ziemlich gut, aber auf einigen Tabellen, die schreiblastig sind, wird es nicht vollständig. Meine Abfrage löscht alle Elemente, denen eine delete
Aktion für eine Kombination aus tupleID und tableName zugeordnet ist:
DELETE FROM track_table WHERE tableName='someTable' AND tupleID IN (
SELECT DISTINCT tupleID FROM track_table
WHERE tableName='someTable' AND action='DELETE' AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
)
Ich habe dies 3 Tage lang auf meinem Server laufen lassen und es wurde für die größte Tabelle nie abgeschlossen. Die EXPLAIN-Ausgabe (wenn ich das Löschen auf Auswahl umschalte:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | PRIMARY | track_table | ref | tableID | tableID | 257 | const | 3941832 | Using where |
| 2 | DEPENDENT SUBQUERY | track_table | ref | tableID,actionDate | tableID | 261 | const,func | 1 | Using where; Using temporary |
Das Löschen von 4 Millionen Zeilen sollte also nicht 3 Tage dauern, würde ich denken. Ich habe meine innodb_buffer_pool_size auf 3 GB festgelegt, und der Server ist nicht für die Verwendung von one_file_per_table festgelegt. Welche anderen Möglichkeiten kann ich die Leistung beim Löschen von InnoDB verbessern? (Ausführen von MySQL 5.1.43 unter Mac OS X)
quelle
Das Löschen unerwünschter Zeilen im Stapel sollte andere Vorgänge funktionsfähig halten. Für das Löschen des Vorgangs gelten jedoch Bedingungen. Stellen Sie daher sicher, dass für Spalten über Bedingungen ein geeigneter Index vorhanden ist.
Da MySQL die vollständige Funktion des losen Index-Scans nicht unterstützt, können Sie versuchen, die Reihenfolge für
KEY actionDate (action, date_insert)
bis anzupassenKEY actionDate (date_insert, action)
. Mit dem Präfix 'date_insert' sollte MySQL diesen Index verwenden, um die Zeilen zu scannen, die vor Ihrer datetime-Bedingung liegen.Mit einem solchen Index können Sie SQL schreiben als:
quelle
-Fist, aus Ihrer Erklärung der key_len so groß => müssen Sie die Größe so klein wie möglich herabstufen. Für Ihre Abfrage ist es meiner Meinung nach am besten, den Datentyp des Aktionsfelds von char (12) in tinyint zu ändern, sodass die Datenzuordnung folgendermaßen aussieht:
und Sie können anstelle des Tabellennamens auch table_id ändern. Die DDL für die beste Leistung kann:
Die Abfrage kann also folgendermaßen aussehen:
Der schnellste Weg war jedoch die Verwendung der Partition. So können Sie Partition löschen. Derzeit hat mein Tisch mehr als 40mil Zeilen. und stündlich aktualisieren (400.000 Zeilen werden jedes Mal aktualisiert), und ich kann die curr_date-Partition löschen und Daten in die Tabelle neu laden. Der Drop-Befehl ist sehr schnell (<100 ms). Ich hoffe das hilft.
quelle