MySQL 5.1 bis 5.6: massiver Leistungseinbruch

7

Okay, das sind möglicherweise drei Fragen. Ich möchte meine vorhandene MySQL 5.1-Datenbank mit MyISAM auf 5.6 mit InnoDB verschieben, und zwar aus einer Reihe von offensichtlichen - und möglicherweise sogar guten - Gründen.

Dies ist auf Amazon RDS, daher beschränkt sich meine Upgrade-Route auf das Dumping und die Neuerstellung der Datenbank.

Ich gebe fröhlich zu, dass ich kein hoch entwickelter DBA bin.

Problem 1: Wow ist so langsam!

Es dauert ungefähr 15 Minuten bis zu mysqldumpunseren etwa 160 Millionen Reihen. (Show Tisch usw. kommt, halten Sie Ihre Pferde.)

Es dauerte ungefähr 50 Stunden , um es in eine MySQL 5.6-Instanz mit einer Engine zu laden, die geschickt in InnoDB geschrieben wurde.

Problem 2: Wo sind meine Zeilen ?

select count(*) from node;auf die aktuelle DB gibt rund 162 Millionen. Auf dem 5.6 gibt es rund 93 Millionen. Die Ladung schien erfolgreich zu sein, obwohl ich es nicht beweisen kann; Zumindest gab es keine Fehlermeldung, nachdem das Laden beendet wurde.

Wenn es nicht erfolgreich war, war das sehr langsam.

Problem 3: WOW ist so langsam!

Die select count(*) from node;Fertigstellung erfolgt also in kürzester Zeit - zwischen 0,00 und 0,03 Sekunden nach den Abfrageergebnissen - auf 5.1. Bei 5.6 mit InnoDB dauert es über eine Minute. Die Erklärung macht deutlich, dass dies auf einen Unterschied in der Art und Weise zurückzuführen ist, wie die Abfrage optimiert wird - aber unklar, warum sie anders ist.

Tabellen und Erklärungen

MySQL 5.1

mysql> show create table node\G
*************************** 1. row ***************************
       Table: node
Create Table: CREATE TABLE `node` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `graph` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `subject` varchar(200) NOT NULL,
  `predicate` varchar(200) NOT NULL,
  `object` mediumtext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `nodeindex` (`graph`(20),`subject`(100),`predicate`(100),`object`(100)),
  KEY `ix_node_subject` (`subject`),
  KEY `ix_node_graph` (`graph`),
  KEY `ix_node_object` (`object`(255)),
  KEY `ix_node_predicate` (`predicate`),
  KEY `node_po` (`predicate`,`object`(130)),
  KEY `node_so` (`subject`,`object`(130)),
  KEY `node_sp` (`subject`,`predicate`(130)),
  FULLTEXT KEY `node_search` (`object`)
) ENGINE=MyISAM AUTO_INCREMENT=550671861 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> select count(id) from node;
+-----------+
| count(id) |
+-----------+
| 163426434 |
+-----------+
1 row in set (0.00 sec)


mysql> explain select count(id) from node;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.00 sec)

MySQL 5.6

mysql> show create table node\G
*************************** 1. row ***************************
       Table: node
Create Table: CREATE TABLE `node` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `graph` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `subject` varchar(200) NOT NULL,
  `predicate` varchar(200) NOT NULL,
  `object` mediumtext NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `nodeindex` (`graph`(20),`subject`(100),`predicate`(100),`object`(100)),
  KEY `ix_node_subject` (`subject`),
  KEY `ix_node_graph` (`graph`),
  KEY `ix_node_object` (`object`(255)),
  KEY `ix_node_predicate` (`predicate`),
  KEY `node_po` (`predicate`,`object`(130)),
  KEY `node_so` (`subject`,`object`(130)),
  KEY `node_sp` (`subject`,`predicate`(130)),
  FULLTEXT KEY `node_search` (`object`)
) ENGINE=InnoDB AUTO_INCREMENT=481239575 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

`` `

mysql> explain select count(id) from node;
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows     | Extra       |
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
|  1 | SIMPLE      | node  | index | NULL          | ix_node_graph | 103     | NULL | 79671827 | Using index |
+----+-------------+-------+-------+---------------+---------------+---------+------+----------+-------------+
1 row in set (0.00 sec)
Charlie Martin
quelle

Antworten:

8

Ihre Probleme haben nichts mit der Version von MySQL zu tun. Es hat mit der Storage Engine zu tun.

Antwort auf PROBLEM 1: Wow ist so langsam!

Das Ausführen von mysqldump berührt nur Daten aus der .MYDDatei der MyISAM-Tabelle. Daher finde ich es nicht überraschend, 163 Millionen Zeilen in 15 Minuten zu löschen.

Das Laden von Daten in Amazon RDS, das 50 Stunden dauert, ist auch für mich kein Schock. Warum ?

Unabhängig davon, welches Servermodell Sie für MySQL RDS auswählen, sind InnoDB-Transaktionsprotokolle (ib_logfile0, ib_logfile1) immer 128 MB groß und dürfen nicht geändert werden, auch nicht die RDS-CLI . Ich habe darüber schon einmal geschrieben: Lokale Datenbank gegen Amazon RDS

Alle Schreibvorgänge in InnoDB werden in den Double Write Buffer geschrieben.> Sie sollten ihn vor dem Laden deaktivieren: Siehe meinen Beitrag Möglichkeiten zur Beschleunigung von InnoDB INSERTs und UPDATEs

Jeder Zeilenblock aus jedem INSERT wird als Transaktion behandelt, wobei Daten über den doppelten Schreibpuffer von ibdata1 und die Transaktionsprotokolle geschrieben werden. Also die Langsamkeit.

Antwort auf PROBLEM 2: Wo sind meine Zeilen?

Schau dir das an nodeindex. Ich kann sehen, dass es sich um einen Präfixindex handelt.

Laut der MySQL-Dokumentation zuCREATE INDEX :

Die Präfixunterstützung und die Länge der Präfixe (sofern unterstützt) hängen von der Speicher-Engine ab. Beispielsweise kann ein Präfix für MyISAM-Tabellen bis zu 1000 Byte und für InnoDB-Tabellen bis zu 767 Byte lang sein.

Ich kann fast garantieren, dass eine Zeile mit einer Länge von graph,subject,predicate,objectmehr als 767 nicht in die InnoDB-Tabelle gelangt ist.

Antwort auf PROBLEM 3: Wow ist so langsam!

Dies liegt an der Storage Engine.

Wenn Sie select count(id) from node;gegen ein MyISAM laufen , betrügt MyISAM und greift in den .MYDHeader, um die Zeilenanzahl zu erhalten. Somit ist die Laufzeit zum Abrufen einer Zeilenanzahl keine Funktion der tatsächlichen Anzahl von Zeilen. Auf diese Weise optimiert das MySQL Query Optimizer alle Standardmechanismen und gibt Ihnen eine Zeilenanzahl.

Wenn es um InnoDB geht, muss eine Tabelle jedes Mal vollständig gescannt werden, da die Zeilenanzahl nicht gespeichert wird: Siehe meinen Beitrag Warum speichert InnoDB die Zeilenanzahl nicht?

VORSCHLAG

Ich würde es nicht als InnoDB importieren. Ich würde zuerst MyISAM importieren. Konvertieren Sie dann alle Ihre MyISAM-Tabellen in InnoDB. Bevor Sie es konvertieren, müssen Sie es möglicherweise ändern nodeindexoder ganz entfernen. Andernfalls verlieren Sie die Zeilen bei der Konvertierung.

Siehe meinen Beitrag Welche zuerst: MySQL-Version aktualisieren oder Speicher-Engine konvertieren? für mehr Informationen.

RolandoMySQLDBA
quelle
Vielen Dank. Hmmm. Ich habe vor, die Datenbank für eine Weile zu wiederholen und die massiven VARCHARS - die nur in der Nähe von 50 verschiedenen Werten liegen - durch einen Index in eine andere Tabelle zu ersetzen und den FULLTEXT in eine separate Tabelle zu verschieben. Es hört sich so an, als würde ich nicht viel aus InnoDB herausholen, ohne die Kugel darauf zu beißen.
Charlie Martin