High Disk IO, wie zu mildern?

8

Ich bin ein Programmierer, kein DBA. Sei sanft :)

Überblick

  • InnoDB, MySQL
  • mod_perl Skript, dauerhafte Verbindungen
  • Skript, das alle 20 Sekunden von Tausenden von Benutzern aufgerufen wird

Problem

  • High Disk IO (vermutlich verursacht durch Updates [?]) Verlangsamt alles und führt zu einem großen Engpass.

Abfragen

  1. UPDATE [einzelne Tabelle] SET refreshTime auf den aktuellen Zeitstempel setzen, mit zwei gleichen Tabellenprüfungen in der WHERE-Klausel
  2. SELECT COUNT (*) [vier Tabellenverknüpfungen mit Indizes] und eine Reihe von ANDs in der WHERE-Klausel (immer noch ziemlich einfach)
  3. SELECT a, b [vier Tabellenverknüpfungen, dieselben vier Tabellen] und eine Reihe von UNDs in der WHERE-Klausel (ebenfalls ziemlich einfach)

Der Abfragecache ist aktiviert.

Lösungen?

  • Ich bin kein DBA, aber ich vermute, dass es möglich ist, eine Tabelle im RAM zu haben, die regelmäßig (alle 10 Sekunden?) Auf die Festplatte aktualisiert wird und im Falle eines katastrophalen Fehlers die RAM-Tabelle automatisch aus der Festplattentabelle auffüllt beim Neustart, aber ich habe keine Ahnung, ob es tatsächlich möglich ist, ob es die beste Lösung ist oder welche anderen Optionen es gibt.
  • Irgendwelche Gedanken oder Vorschläge? Auch hier bin ich Programmierer. Wenn also jemand jemanden kennt, der dies gegen eine Gebühr tut, oder mich auf ganz bestimmte Ressourcen verweisen kann, wäre ich sehr dankbar.

~~~~~~~~

CREATE TABLE `openInvitations` (
`id` int(99) NOT NULL auto_increment,
`createTime` timestamp NULL default NULL,
`repAcceptTime` timestamp NULL default NULL,
`rep_id` varchar(64) NOT NULL default '',
`repRefreshTime` timestamp NULL default NULL,
`customer_macAddr` varchar(14) NOT NULL default '',
`customerRefreshTime` timestamp NULL default NULL,
`stage` char(1) NOT NULL default 'P',
`parent` varchar(25) default NULL,
`reason` varchar(64) default NULL,
PRIMARY KEY  (`rep_id`,`customer_macAddr`),
UNIQUE KEY `id` (`id`),
KEY `customer_macAddr` (`customer_macAddr`),
CONSTRAINT `openInvitations_ibfk_1` FOREIGN KEY (`rep_id`) REFERENCES `rep` (`id`),
CONSTRAINT `openInvitations_ibfk_2` FOREIGN KEY (`customer_macAddr`) REFERENCES `customer` (`macAddr`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1
id select_type Tabellentyp möglichen_Tasten key key_len ref Zeilen Extra
1 EINFACH oi ref PRIMARY, customer_macAddr customer_macAddr 16 const 1 Using where; Index verwenden
1 SIMPLE r eq_ref PRIMARY, FK_rep_1 PRIMARY 66 xxx.oi.rep_id 1 Verwenden von where
1 SIMPLE s eq_ref PRIMARY, FK_subscriber_1 PRIMARY 27 xxx.r.subscriber_id 1 Verwenden von where
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 xxx.s.charge_id 1 Verwenden von where
id select_type Tabellentyp möglichen_Tasten key key_len ref Zeilen Extra
1 EINFACH oi ref PRIMARY, customer_macAddr customer_macAddr 16 const 1 Using where
1 SIMPLE r eq_ref PRIMARY, FK_rep_1 PRIMARY 66 xxx.oi.rep_id 1 Verwenden von where
1 SIMPLE s eq_ref PRIMARY, FK_subscriber_1 PRIMARY 27 xxx.r.subscriber_id 1 Verwenden von where
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 xxx.s.charge_id 1 Verwenden von where
id select_type Tabellentyp möglichen_Tasten key key_len ref Zeilen Extra
1 EINFACH openInvitations ALL customer_macAddr NULL NULL NULL 5258 Verwenden von where

Nach dem Beheben der Abfrage:

id select_type Tabellentyp möglichen_Tasten key key_len ref Zeilen Extra
1 SIMPLE openInvitations ref customer_macAddr customer_macAddr 16 const 1 Using where
Disko
quelle
3
Hallo Disco, willkommen bei den Datenbankadministratoren . Zunächst müssen Sie die EXPLAINAusgabe Ihrer ausgewählten Abfragen bereitstellen und SHOW CREATE TABLE updateTableuns dabei helfen. Es ist wahrscheinlich ein Indexierungsproblem.
Derek Downey
Vielen Dank. Ich habe die oben angeforderten Informationen angehängt. Wenn Sie die EXPLAIN für das UPDATE oder etwas anderes benötigen, lassen Sie es mich bitte wissen.
Disco
+1, um es selbst zu beheben :) Manchmal kann eine detaillierte Erklärung des Problems zeigen, wo Ihre eigenen Fehler liegen!
Dave Rix
1
Ich würde vorschlagen, Ihre eigene Antwort hinzuzufügen und die alten und neuen Versionen der Abfragen anzuzeigen. In ein paar Tagen können Sie Ihre eigene Antwort akzeptieren, und dann wird diese Frage nicht mehr in den "unbeantworteten" Listen auftauchen :)
Dave Rix

Antworten:

7

Geben Sie, wie DTest hervorhob, weitere Informationen zu Ihrem Problem an.

In Bezug auf das Caching können Sie möglicherweise die Größe Ihres Innodb-Pufferpools erhöhen, damit mehr Daten und Indizes im Speicher zwischengespeichert werden können. Wenn Sie häufig aktualisiert werden, profitieren Sie möglicherweise nicht vom Abfrage-Cache und verwenden diesen RAM möglicherweise besser für den Innodb-Pufferpool.

Wenn Sie alle Ihre Daten und Indizes im RAM ablegen möchten, ist MySQL Cluster möglicherweise Ihre Antwort.

BEARBEITEN
Es sieht so aus, als würden Ihre SELECT-Anweisungen die richtigen Indizes verwenden. Könnten Sie einen Erklärungsplan für Ihre Update-Anweisung bereitstellen? Sie müssen es als SELECT-Anweisung umschreiben, um dies zu tun. Führen Sie SELECT * FROMdieselbe Tabelle und dieselbe where-Klausel wie Ihre UPDATE-Anweisung aus.

dabest1
quelle
3
Von George, ich denke, das hat es gefunden. :) Ich denke, es ist ein Fehler in der Abfrage selbst, der, obwohl er funktioniert, mehrere tausend Zeilen mehr als nötig aktualisiert. Läuft über Nacht und wird am Morgen aktualisiert. Vielen Dank!
Disco
3
Es ist viel besser. Das Problem war, dass ich in einem meiner OPs keinen Schlüssel hatte. Was ist die DBA StackExchange Community-Etikette hier? Markiere ich diese Antwort als "richtig" oder beantworte ich meine eigene Frage und markiere sie als richtig?
Disco
Gut! Ich bin auch hier noch neu, daher kenne ich die richtige Etikette nicht. Dies ist eine Frage, die Sie auf der DBA-Metaseite stellen sollten.
dabest1
Wie wäre es, wenn Sie Ihre Antwort so bearbeiten, dass sie den OP im Update überprüft, und ich werde sie als korrekt markieren? :)
Disco
@Disco, mach weiter und erstelle deine Antwort mit der Erklärung und markiere sie als richtig. Das ist ok für mich.
dabest1
5

Das Problem war darauf zurückzuführen, dass in einer meiner OR-Anweisungen im UPDATE kein Schlüssel enthalten war.

Hutspitze zu "dabest1", um mir zu helfen, die Antwort zu finden.

Disko
quelle