Ich habe die Ergebnisse von einem Algorithmus geschrieben, der Abstände zwischen Kunden in einer InnoDB-Tabelle berechnet. Zum Beispiel, wenn meine Kunden A, B, C und D in der Datenbank die Tabelle sieht wie folgt aus, unter anderem Spalten:In diesem Fall ist MyISAM dramatisch schneller als InnoDB in mysql
From | To | Distance
A B 344
A C 274
A D 182
B C 338
Und so weiter ... Es ist eine Menge von Zeilen denke ich, werde ich Treffer 50 Millionen.
Die anderen Spalten sind product_type und value. Diese sagen mir, wie viel der Kunde B (customer_to in den Spalten) dieses product_type kauft. Das bedeutet, dass ich jedes Paar mehrere Male habe, abhängig davon, wie viele Produkttypen der Kunde B kauft.
Ich musste zu einer Abfrage, um jeden Kunden mit den Produkten zu gruppieren, die seine Nachbarn kaufen und den Wert. Die Abfrage sieht so aus:
select customer_from, product_type, avg(value) as opportunity
from customer_distances
where distance < 500
group by customer_from, product_type
order by opportunity desc;
Die innodb Tabelle konnte mir diese Abfrage nicht beantworten. Obwohl ich net_read_timeout auf 28800 änderte, ging die mysql-Verbindung während der Abfrage verloren.
Ich hatte es schwer mit Innodb Build für Transaktionsverarbeitung und nicht für intensive Abfragen zu tun. Also habe ich eine neue Tabelle mit MyIsam als Engine erstellt und füge alle Datensätze aus der innodb-Tabelle ein.
Wie erwartet, war die Auswahl sehr schnell (70 segs) und alle anderen wählt wie count (distinct customer_from), wo fast sofort.
Nur aus Neugier habe ich versucht, den Prozess der Einfügung der Abstände in der Myisam-Tabelle fortzusetzen. Es war eine Überraschung für mich, als das Programm mindestens 100-mal schneller lief als bei der Arbeit am innodb-Tisch - für INSERTS!
Für jeden Kunden fügt das Programm etwa 3000 Zeilen ein (eine für jeden Nachbarn für jeden product_type. Etwas wie 300 Nachbarn und 10 product_types pro Kunde). Mit dem innodb-Tisch hat das Einfügen eines einzelnen Kunden zwischen 40 und 60 Sekunden (ca. 3000 Zeilen) gedauert. Mit der Myisam-Tabelle dauert es 1 Sekunde, um 3 Kunden einzufügen (9000 Zeilen aprox).
Einige zusätzliche Informationen:
- Die MySQL-Datenbank in meinem PC ist (localhost).
- Das Programm in Java geschrieben und läuft von meinem PC.
- Ich verwende vorbereitete Anweisungen und ich ändere nur die Daten zwischen jeder Reihe und der nächsten. Dies wird auf diese Frage im Zusammenhang Why is myisam storage engine is faster than Innodb storage engine
Also zusammenfassend die Frage ist: Warum ist MyISAM, die schnell mit Insert-Anweisungen? Was denkst du?
EDIT 1: Ich bin die create-Anweisungen für beide Tabellen hinzufügen, die Innodb und Myisam. EDIT 2: Ich habe einige unbrauchbare Informationen gelöscht und ein bisschen hier und da formatiert.
/* INNODB TABLE */
CREATE TABLE `customer_distances` (
`customer_from` varchar(50) NOT NULL,
`customer_from_type` varchar(50) DEFAULT NULL,
`customer_from_segment` varchar(50) DEFAULT NULL,
`customer_from_district` int(11) DEFAULT NULL,
`customer_from_zone` int(11) DEFAULT NULL,
`customer_from_longitud` decimal(15,6) DEFAULT NULL,
`customer_from_latitud` decimal(15,6) DEFAULT NULL,
`customer_to` varchar(50) NOT NULL,
`customer_to_type` varchar(50) DEFAULT NULL,
`customer_to_segment` varchar(50) DEFAULT NULL,
`customer_to_district` int(11) DEFAULT NULL,
`customer_to_zone` int(11) DEFAULT NULL,
`customer_to_longitud` decimal(15,6) DEFAULT NULL,
`customer_to_latitud` decimal(15,6) DEFAULT NULL,
`distance` decimal(10,2) DEFAULT NULL,
`product_business_line` varchar(50) DEFAULT NULL,
`product_type` varchar(50) NOT NULL,
`customer_from_liters` decimal(10,2) DEFAULT NULL,
`customer_from_dollars` decimal(10,2) DEFAULT NULL,
`customer_from_units` decimal(10,2) DEFAULT NULL,
`customer_to_liters` decimal(10,2) DEFAULT NULL,
`customer_to_dollars` decimal(10,2) DEFAULT NULL,
`customer_to_units` decimal(10,2) DEFAULT NULL,
`liters_opportunity` decimal(10,2) DEFAULT NULL,
`dollars_opportunity` decimal(10,2) DEFAULT NULL,
`units_oportunity` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`cliente_desde`,`cliente_hasta`,`grupo`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/* MYISAM TABLE */
CREATE TABLE `customer_distances` (
`customer_from` varchar(50) NOT NULL,
`customer_from_type` varchar(50) DEFAULT NULL,
`customer_from_segment` varchar(50) DEFAULT NULL,
`customer_from_district` int(11) DEFAULT NULL,
`customer_from_zone` int(11) DEFAULT NULL,
`customer_from_longitud` decimal(15,6) DEFAULT NULL,
`customer_from_latitud` decimal(15,6) DEFAULT NULL,
`customer_to` varchar(50) NOT NULL,
`customer_to_type` varchar(50) DEFAULT NULL,
`customer_to_segment` varchar(50) DEFAULT NULL,
`customer_to_district` int(11) DEFAULT NULL,
`customer_to_zone` int(11) DEFAULT NULL,
`customer_to_longitud` decimal(15,6) DEFAULT NULL,
`customer_to_latitud` decimal(15,6) DEFAULT NULL,
`distance` decimal(10,2) DEFAULT NULL,
`product_business_line` varchar(50) DEFAULT NULL,
`product_type` varchar(50) NOT NULL,
`customer_from_liters` decimal(10,2) DEFAULT NULL,
`customer_from_dollars` decimal(10,2) DEFAULT NULL,
`customer_from_units` decimal(10,2) DEFAULT NULL,
`customer_to_liters` decimal(10,2) DEFAULT NULL,
`customer_to_dollars` decimal(10,2) DEFAULT NULL,
`customer_to_units` decimal(10,2) DEFAULT NULL,
`liters_opportunity` decimal(10,2) DEFAULT NULL,
`dollars_opportunity` decimal(10,2) DEFAULT NULL,
`units_oportunity` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`cliente_desde`,`cliente_hasta`,`grupo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Waren die Tabellen ansonsten identisch (Indizes, etc ...)? Außerdem gibt es separate Servereinstellungen (z. B. Speichercachegrößen) für die Engines, die die Leistung beeinträchtigen könnten. – Uueerdo
Sie sollten die Produktverkaufsdaten normalisieren. Die Tabelle macht keinen Sinn, wie sie derzeit entworfen ist. – EJP
Identische Tabellen, gleiche Server. –