Verwenden von MySQL 5.6 mit der InnoDB-Speicher-Engine für die meisten Tabellen. Die Größe des InnoDB-Pufferpools beträgt 15 GB, und die Innodb DB + -Indizes liegen bei etwa 10 GB. Der Server verfügt über 32 GB RAM und führt Cent OS 7 x64 aus.
Ich habe einen großen Tisch, der über 10 Millionen Datensätze enthält.
Ich erhalte alle 24 Stunden eine aktualisierte Dump-Datei von einem Remote-Server. Die Datei ist im CSV-Format. Ich habe keine Kontrolle über dieses Format. Die Datei ist ~ 750 MB groß. Ich habe versucht, Daten zeilenweise in eine MyISAM-Tabelle einzufügen, und es dauerte 35 Minuten.
Ich muss nur 3 Werte pro Zeile von 10-12 aus der Datei entnehmen und in der Datenbank aktualisieren.
Was ist der beste Weg, um so etwas zu erreichen?
Ich muss das täglich tun.
Momentan sieht Flow so aus:
- mysqli_begin_transaction
- Dump-Datei Zeile für Zeile lesen
- Aktualisieren Sie jeden Datensatz Zeile für Zeile.
- mysqli_commit
Die oben genannten Vorgänge dauern ca. 30-40 Minuten. Dabei werden noch weitere Aktualisierungen durchgeführt, die ich erhalten kann
Wartezeitüberschreitung der Sperre überschritten; Starten Sie die Transaktion erneut
Update 1
Daten laden in neue Tabelle mit LOAD DATA LOCAL INFILE. In MyISAM hat es gedauert, 38.93 secwährend es in InnoDB 7 Minuten 5,21 Sekunden gedauert hat. Dann habe ich gemacht:
UPDATE table1 t1, table2 t2
SET
t1.field1 = t2.field1,
t1.field2 = t2.field2,
t1.field3 = t2.field3
WHERE t1.field10 = t2.field10
Query OK, 434914 rows affected (22 hours 14 min 47.55 sec)
Update 2
Gleiches Update mit Join-Abfrage
UPDATE table1 a JOIN table2 b
ON a.field1 = b.field1
SET
a.field2 = b.field2,
a.field3 = b.field3,
a.field4 = b.field4
(14 hours 56 min 46.85 sec)
Erläuterungen zu Fragen in Kommentaren:
- Ungefähr 6% der Zeilen in der Tabelle werden von der Datei aktualisiert, aber manchmal können es bis zu 25% sein.
- Es gibt Indizes für die Felder, die aktualisiert werden. Die Tabelle enthält 12 Indizes, und 8 Indizes enthalten die Aktualisierungsfelder.
- Es ist nicht erforderlich , das Update in einer Transaktion durchzuführen. Es kann einige Zeit dauern, aber nicht länger als 24 Stunden. Ich versuche, es in 1 Stunde zu erledigen, ohne die gesamte Tabelle zu sperren, da ich später den von dieser Tabelle abhängigen Sphinx-Index aktualisieren muss. Es spielt keine Rolle, ob die Schritte länger dauern, solange die Datenbank für andere Aufgaben verfügbar ist.
- Ich könnte das CSV-Format in einem Vorverarbeitungsschritt ändern. Das einzige, was zählt, ist ein schnelles Update und ohne Sperren.
- Tabelle 2 ist MyISAM. Dies ist die neu erstellte Tabelle aus der CSV-Datei, die die Ladedaten-Datei verwendet. MYI Dateigröße beträgt 452 MB. Tabelle 2 ist in der Spalte field1 indiziert.
- MYD der MyISAM-Tabelle ist 663 MB.
Update 3:
Hier finden Sie weitere Details zu beiden Tabellen.
CREATE TABLE `content` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`og_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`keywords` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`files_count` smallint(5) unsigned NOT NULL DEFAULT '0',
`more_files` smallint(5) unsigned NOT NULL DEFAULT '0',
`files` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`category` smallint(3) unsigned NOT NULL DEFAULT '600',
`size` bigint(19) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) NOT NULL DEFAULT '0',
`completed` int(11) NOT NULL DEFAULT '0',
`uploaders` int(11) NOT NULL DEFAULT '0',
`creation_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`upload_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`vote_up` int(11) unsigned NOT NULL DEFAULT '0',
`vote_down` int(11) unsigned NOT NULL DEFAULT '0',
`comments_count` int(11) NOT NULL DEFAULT '0',
`imdb` int(8) unsigned NOT NULL DEFAULT '0',
`video_sample` tinyint(1) NOT NULL DEFAULT '0',
`video_quality` tinyint(2) NOT NULL DEFAULT '0',
`audio_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`subtitle_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`uploader` int(11) unsigned NOT NULL DEFAULT '0',
`anonymous` tinyint(1) NOT NULL DEFAULT '0',
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`tfile_size` int(11) unsigned NOT NULL DEFAULT '0',
`scrape_source` tinyint(1) unsigned NOT NULL DEFAULT '0',
`record_num` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`record_num`),
UNIQUE KEY `hash` (`hash`),
KEY `uploaders` (`uploaders`),
KEY `tfile_size` (`tfile_size`),
KEY `enabled_category_upload_date_verified_` (`enabled`,`category`,`upload_date`,`verified`),
KEY `enabled_upload_date_verified_` (`enabled`,`upload_date`,`verified`),
KEY `enabled_category_verified_` (`enabled`,`category`,`verified`),
KEY `enabled_verified_` (`enabled`,`verified`),
KEY `enabled_uploader_` (`enabled`,`uploader`),
KEY `anonymous_uploader_` (`anonymous`,`uploader`),
KEY `enabled_uploaders_upload_date_` (`enabled`,`uploaders`,`upload_date`),
KEY `enabled_verified_category` (`enabled`,`verified`,`category`),
KEY `verified_enabled_category` (`verified`,`enabled`,`category`)
) ENGINE=InnoDB AUTO_INCREMENT=7551163 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED
CREATE TABLE `content_csv_dump_temp` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`category_id` int(11) unsigned NOT NULL DEFAULT '0',
`uploaders` int(11) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) unsigned NOT NULL DEFAULT '0',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
und hier ist die Aktualisierungsabfrage, die die contentTabelle unter Verwendung von Daten aus aktualisiertcontent_csv_dump_temp
UPDATE content a JOIN content_csv_dump_temp b
ON a.hash = b.hash
SET
a.uploaders = b.uploaders,
a.downloaders = b.downloaders,
a.verified = b.verified
Update 4:
Alle oben genannten Tests wurden auf einer Testmaschine durchgeführt, aber jetzt habe ich dieselben Tests auf der Produktionsmaschine durchgeführt, und die Abfragen sind sehr schnell.
mysql> UPDATE content_test a JOIN content_csv_dump_temp b
-> ON a.hash = b.hash
-> SET
-> a.uploaders = b.uploaders,
-> a.downloaders = b.downloaders,
-> a.verified = b.verified;
Query OK, 2673528 rows affected (7 min 50.42 sec)
Rows matched: 7044818 Changed: 2673528 Warnings: 0
Ich entschuldige mich für meinen Fehler. Es ist besser, Join anstelle jedes Datensatzupdates zu verwenden. Jetzt versuche ich, mpre mit dem von rick_james vorgeschlagenen Index zu verbessern. Wird aktualisiert, sobald das Benchmarking abgeschlossen ist.
UPDATEs . Bitte teilen Sie uns genau mit, wie die einfache Anweisung zum Aktualisieren der Tabelle aus den CSV-Daten aussieht. Dann können wir Ihnen möglicherweise dabei helfen, eine Technik zu entwickeln, die Ihren Anforderungen entspricht.
update, und überprüfen Sie bitte aktualisierte Frage., Danke
INDEX(field2, field3, field4)(in beliebiger Reihenfolge)? Bitte zeigen Sie unsSHOW CREATE TABLE.