Ganz gleich, ob es sich um die tägliche Verarbeitung von Geschäftsdaten oder um den Import und Export von Datenbanken handelt, Sie können auf Einfügungen stoßen, die die Verarbeitung großer Datenmengen erfordern. Sowohl die Einfügemethode als auch die Datenbank-Engine wirken sich auf die Einfügegeschwindigkeit aus. Ziel dieses Artikels ist es, verschiedene Methoden aus theoretischer und praktischer Sicht zu analysieren und zu vergleichen, um die Auswahl von Einfügemethoden in zukünftigen Anwendungen zu erleichtern.
Die zum Einfügen eines Datensatzes in MySQL benötigte Zeit setzt sich aus folgenden Faktoren zusammen, wobei die Zahlen ungefähre Proportionen darstellen:
Verbindung : (3 )
Abfrage an Server senden: (2)
Abfrage analysieren: (2)
Datensatz einfügen: (1x Datensatzgröße)
Index einfügen: (1x Index)
Schließen: (1)
Wenn wir jedes Mal, wenn wir ein Element einfügen, eine SQL-Anweisung ausführen, müssen wir alle Schritte außer dem Verbinden und Schließen N-mal ausführen. Es gibt mehrere Optimierungsmethoden:
Schreiben Sie mehrere Zeilen in jede Einfügeanweisung, Batch-Einfügung
Schreiben Sie alle Abfrageanweisungen in die Transaktion
Verwenden Sie „Daten laden“, um Daten zu importieren
Die Leistung jeder Methode ist wie folgt.
InnoDB stellt MySQL transaktionssichere (ACID-kompatible) Transaktions- (Commit-), Rollback- (Rollback-) und Crash-Recovery-Funktionen (Crash Recovery Capabilities) zur Verfügung. InnoDB bietet Zeilensperren (Sperren auf Zeilenebene) und Fremdschlüsseleinschränkungen (FOREIGN KEY-Einschränkungen).
InnoDB ist für den Umgang mit Datenbanksystemen mit großer Kapazität konzipiert und seine CPU-Auslastung wird von anderen festplattenbasierten relationalen Datenbank-Engines nicht erreicht. Technisch gesehen ist InnoDB ein vollständiges Datenbanksystem auf dem MySQL-Hintergrund. InnoDB richtet im Hauptspeicher einen eigenen Pufferpool für die Zwischenspeicherung von Daten und Indizes ein.
Macbook Air 12mid apache2.2.26 php5.5.10 mysql5.6.16
Insgesamt 1 Million Datenstücke
Nach dem Einfügen die Datenbankgröße ist 38,6 MB (kein Index), 46,8 (mit Index)
Gesamtzeit für einzelnes Einfügen ohne Index: 229 s Spitzenspeicher: 246 KB
Einzelnes Einfügen mit Index Gesamtzeit: 242 s Spitzenspeicher: 246 KB
Gesamtzeit für Stapeleinfügung ohne Index: 10 s Spitzenspeicher: 8643 KB
Batch-Einfügung mit Index Gesamtzeit: 16 s Spitzenspeicher: 8643 KB
Gesamtzeit für das Einfügen von Transaktionen ohne Index: 78 s Spitzenspeicher: 246 KB
Einfügung mit indizierter Transaktion Gesamtzeit: 82 Sekunden Spitzenspeicher: 246 KB
Laden ohne Index Gesamtzeit für das Einfügen von Daten: 12 Sekunden Spitzenspeicher: 246 KB
Laden mit Index Gesamtdateneinfügungszeit: 11 s Spitzenspeicher: 246 KB
MyISAM ist die Standardspeicher-Engine von MySQL. Das Design ist einfach und unterstützt die Volltextsuche.
Macbook Air 12mid apache2.2.26 php5.5.10 mysql5.6.16
Insgesamt 1 Million Datenstücke
Nach dem Einfügen die Datenbankgröße ist 19,1 MB (kein Index), 38,6 (mit Index)
Gesamtzeit für einzelnes Einfügen ohne Index: 82 s Spitzenspeicher: 246 KB
Einzelnes Einfügen mit Index Gesamtzeit: 86 s Spitzenspeicher: 246 KB
Gesamtzeit für Stapeleinfügung ohne Index: 3 s Spitzenspeicher: 8643 KB
Stapeleinfügung mit Index Gesamtzeit: 7 s Spitzenspeicher: 8643 KB
Laden ohne Index Gesamtzeit für das Einfügen von Daten: 6 s Spitzenspeicher: 246 KB
Mit Index laden Gesamte Dateneinfügungszeit: 8 s Spitzenspeicher: 246 KB
Die von mir getestete Datenmenge ist nicht sehr groß, aber ich kann sie ungefähr schätzen Verstehen Sie die Geschwindigkeit dieser Einfügemethoden. Die schnellste Methode muss die Methode „Daten laden“ sein. Diese Methode ist relativ mühsam, da sie das Schreiben von Dateien erfordert, kann jedoch sowohl Speicher als auch Geschwindigkeit berücksichtigen.
<?php $dsn = 'mysql:host=localhost;dbname=test'; $db = new PDO($dsn,'root','',array(PDO::ATTR_PERSISTENT => true)); //删除上次的插入数据 $db->query('delete from `test`'); //开始计时 $start_time = time(); $sum = 1000000; // 测试选项 $num = 1; if ($num == 1){ // 单条插入 for($i = 0; $i < $sum; $i++){ $db->query("insert into `test` (`id`,`name`) values ($i,'tsetssdf')"); } } elseif ($num == 2) { // 批量插入,为了不超过max_allowed_packet,选择每10万插入一次 for ($i = 0; $i < $sum; $i++) { if ($i == $sum - 1) { //最后一次 if ($i%100000 == 0){ $values = "($i, 'testtest')"; $db->query("insert into `test` (`id`, `name`) values $values"); } else { $values .= ",($i, 'testtest')"; $db->query("insert into `test` (`id`, `name`) values $values"); } break; } if ($i%100000 == 0) { //平常只有在这个情况下才插入 if ($i == 0){ $values = "($i, 'testtest')"; } else { $db->query("insert into `test` (`id`, `name`) values $values"); $values = "($i, 'testtest')"; } } else { $values .= ",($i, 'testtest')"; } } } elseif ($num == 3) { // 事务插入 $db->beginTransaction(); for($i = 0; $i < $sum; $i++){ $db->query("insert into `test` (`id`,`name`) values ($i,'tsetssdf')"); } $db->commit(); } elseif ($num == 4) { // 文件load data $filename = dirname(__FILE__).'/test.sql'; $fp = fopen($filename, 'w'); for($i = 0; $i < $sum; $i++){ fputs($fp, "$i,'testtest'\r\n"); } $db->exec("load data infile '$filename' into table test fields terminated by ','"); } $end_time = time(); echo "总耗时", ($end_time - $start_time), "秒\n"; echo "峰值内存", round(memory_get_peak_usage()/1000), "KB\n"; ?>
Das Obige ist die Leistungsanalyse und der Vergleich verschiedener Methoden zum Einfügen großer Datenmengen in MySQL. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!