Was ist der effizienteste Weg, um UPDATE-Abfragen in MySQL zu stapeln?

10

Ich schreibe eine Anwendung, die über einen längeren Zeitraum eine große Anzahl von Aktualisierungen in der Datenbank löschen muss, und ich bin nicht sicher, wie die Abfrage optimiert werden kann. Derzeit verwende ich INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE, mit dem alle Werte in einer Abfrage zusammengefasst werden, die jedoch in großen Tabellen äußerst langsam ausgeführt wird. Ich muss eigentlich nie Zeilen einfügen.

Andere Ansätze, die ich gesehen habe, sind das Aktualisieren mit SET value = CASE WHEN...(was aufgrund der Art und Weise, wie ich die Abfragen erstelle, und ich bin mir nicht sicher, wie die Leistung von CASEHunderten / Tausenden von Schlüsseln ist) und einfach das mehrfache Verketten Aktualisierung. Wäre beides schneller als meine derzeitige Methode?

Es verwirrt mich, dass es, soweit ich das beurteilen kann, in MySQL keinen idiomatischen und effizienten Weg gibt, dies zu tun. Wenn es wirklich keinen Weg gibt, der schneller ist als ON DUPLICATE KEY, würde es sich lohnen, zu PostgreSQL zu wechseln und dessen UPDATE FROMSyntax zu verwenden?

Alle anderen Vorschläge werden auch sehr geschätzt!

Bearbeiten: Hier ist eine der Tabellen, die häufig aktualisiert wird. Ich habe Spaltennamen entfernt, weil sie irrelevant sind.

CREATE TABLE IF NOT EXISTS `table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `a` bigint(20) unsigned NOT NULL DEFAULT '0',
  `b` bigint(20) unsigned NOT NULL DEFAULT '0',
  `c` enum('0','1','2') NOT NULL DEFAULT '0',
  `d` char(32) NOT NULL,
  -- trimmed --
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `c` (`c`),
  KEY `d` (`d`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
jli
quelle
Dies ist auf einer Testmaschine und nicht in der Produktion, daher ist InnoDB nicht vollständig richtig eingestellt. Ich bin mir nicht ganz sicher, wie INSERT FROM funktioniert, aber was Sie gesagt haben, scheint ungefähr richtig zu sein. Die Frage wurde mit den von Ihnen angeforderten Informationen aktualisiert.
jli

Antworten:

14

Da Sie InnoDBTabellen verwenden, besteht die naheliegendste Optimierung darin, mehrere UPDATEs in einer Transaktion zu gruppieren .

Als InnoDBTransaktionsmodul zahlen Sie nicht nur für sich UPDATEselbst, sondern auch für den gesamten Transaktionsaufwand: Verwalten des Transaktionspuffers, des Transaktionsprotokolls und Löschen des Protokolls auf die Festplatte.

Wenn Sie mit der Idee logisch vertraut sind, versuchen Sie UPDATE, jeweils 100-1000 Sekunden zu gruppieren , jedes Mal wie folgt verpackt:

START TRANSACTION;
UPDATE ...
UPDATE ...
UPDATE ...
UPDATE ...
COMMIT;

Mögliche Nachteile:

  • Ein Fehler führt zum Zusammenbruch der gesamten Transaktion (kann jedoch im Code leicht behoben werden).
  • Möglicherweise warten Sie lange, bis sich Ihre 1000 UPDATESekunden angesammelt haben. Daher möchten Sie möglicherweise auch eine Zeitüberschreitung haben
  • Mehr Komplexität bei Ihrem Anwendungscode.
Shlomi Noach
quelle