it-swarm.com.de

Wie verwende ich die Einfügungsverzögerung mit der InnoDB-Engine und verwende weniger Verbindung für Einfügeanweisungen?

Ich arbeite an einer Anwendung, die viele Datenbankschreibvorgänge, ungefähr 70% Einfügungen und 30% Lesevorgänge umfasst. Dieses Verhältnis würde auch Aktualisierungen einschließen, die ich als ein Lese- und ein Schreibvorgang betrachte. Durch Einfügeanweisungen fügen mehrere Clients Daten in die Datenbank über die folgende Einfügeanweisung ein:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

Die Frage ist, ob ich entweder insert_delay oder mysqli_multi_query Mechanismus wegen insert verwenden soll Anweisung verwendet ~ 100% CPU auf dem Server. Ich verwende die InnoDB-Engine in meiner Datenbank, sodass ein verzögertes Einfügen nicht möglich ist. Das Einfügen auf dem Server ist ~ 36k/h und 99,89% gelesen, außerdem verwende ich dort die select-Anweisung Daten siebenmal in einer einzelnen Abfrage abrufen , diese Abfrage dauert auf dem Server 150 Sekunden. Welche Technik oder welchen Mechanismus kann ich für diese Aufgabe verwenden? Mein Serverspeicher ist 2 GB, sollte ich Speicher erweitern?. Schauen Sie sich dieses Problem an, jeder Vorschlag wird mir dankbar sein.

Struktur der Tabelle:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

Der aktuelle Status meiner Datenbank zeigt 41.000 Einfügungen (Schreibvorgänge) an, was für meine Datenbank sehr langsam ist.

database status

10
Shashank

Da Sie mehr Schreibvorgänge als Lesevorgänge haben, möchte ich Folgendes empfehlen

Eine anständige Abstimmung von InnoDB wäre der Schlüssel

Pufferpool (Größe von innodb_buffer_pool_size )

Da InnoDB INSERT DELAYED nicht unterstützt, ist die Verwendung eines großen InnoDB-Pufferpools am nächsten an INSERT DELAYED. Alle DML (INSERTs, UPDATEs und DELETEs) werden im InnoDB-Pufferpool zwischengespeichert. Transaktionsinformationen für die Schreibvorgänge werden sofort in die Redo-Protokolle (ib_logfile0, ib_logfile1) geschrieben. Die im Pufferpool veröffentlichten Schreibvorgänge werden regelmäßig über ibdata1 (InsertBuffer für Sekundärindizes, Double Write Buffer) vom Speicher auf die Festplatte geleert. Je größer der Pufferpool ist, desto mehr INSERTs können zwischengespeichert werden. Verwenden Sie in einem System mit 8 GB oder mehr RAM 75-80% der RAM als innodb_buffer_pool_size. In einem System mit sehr wenig RAM 25% (um das Betriebssystem aufzunehmen).

CAVEAT: Sie können innodb_doublewrite auf 0 setzen, um das Schreiben noch weiter zu beschleunigen, jedoch unter dem Risiko der Datenintegrität. Sie können die Dinge auch beschleunigen, indem Sie innodb_flush_method auf O_DIRECT setzen, um das Zwischenspeichern von InnoDB an das Betriebssystem zu verhindern.

Protokolle wiederholen (Größe von innodb_log_file_size )

Standardmäßig heißen die Redo-Protokolle ib_logfile0 und ib_logfile1 und betragen jeweils 5 MB. Die Größe sollte 25% der Größe innodb_buffer_pool_size betragen. Wenn die Redo-Protokolle bereits vorhanden sind, fügen Sie die neue Einstellung in my.cnf hinzu, fahren Sie mysql herunter, löschen Sie sie und starten Sie mysql neu .

Protokollpuffer (Größe von innodb_log_buffer_size )

Der Protokollpuffer enthält Änderungen in RAM, bevor sie in die Redo-Protokolle geleert werden. Der Standardwert ist 8 MB. Je größer der Protokollpuffer, desto weniger Festplatten-E/A. Seien Sie bei sehr großen Transaktionen vorsichtig. Dies kann COMMITs um Millisekunden verlangsamen.

Zugriff auf mehrere CPUs

MySQL 5.5 und das MySQL 5.1 InnoDB-Plugin verfügen über Einstellungen, mit denen InnoDB Storage Engine auf mehrere CPUs zugreifen kann. Hier sind die Optionen, die Sie einstellen müssen:

  • innodb_thread_concurrency legt die Obergrenze für die Anzahl gleichzeitiger Threads fest, die InnoDB offen halten kann. Es wird normalerweise empfohlen, hierfür die Einstellung (2 x Anzahl der CPUs) + Anzahl der Festplatten festzulegen. Letztes Jahr habe ich auf der Percona NYC-Konferenz aus erster Hand erfahren, dass Sie diesen Wert auf 0 setzen sollten, um die InnoDB Storage Engine zu warnen, die beste Anzahl von Threads für die Umgebung zu finden, in der sie ausgeführt wird.
  • innodb_concurrency_tickets legt die Anzahl der Threads fest, die die Parallelitätsprüfung ungestraft umgehen können. Nach Erreichen dieses Grenzwerts wird die Überprüfung der Thread-Parallelität wieder zur Norm.
  • innodb_commit_concurrency legt die Anzahl der gleichzeitigen Transaktionen fest, die festgeschrieben werden können. Da der Standardwert 0 ist, kann durch Nichteinstellung einer beliebigen Anzahl von Transaktionen gleichzeitig festgeschrieben werden.
  • innodb_thread_sleep_delay legt die Anzahl der Millisekunden fest, die ein InnoDB-Thread ruhen kann, bevor er erneut in die InnoDB-Warteschlange eingeht. Die Standardeinstellung ist 10000 (10 Sek.).
  • innodb_read_io_threads (setzen Sie dies auf 3000) und innodb_write_io_threads (setzen Sie dies auf 7000) (beide seit MySQL 5.1.38) weisen Sie die angegebene Anzahl von Threads für Lese- und Schreibvorgänge zu. Der Standardwert ist 4 und das Maximum ist 64. Setzen Sie diese auf 64. Setzen Sie außerdem innodb_io_capacity auf 10000.

Upgrade auf MySQL 5.5

Wenn Sie über MySQL 5.0 verfügen, aktualisieren Sie auf MySQL 5.5. Wenn Sie MySQL 5.1.37 oder früher haben, aktualisieren Sie auf MySQL 5.5. Wenn Sie MySQL 5.1.38 oder höher haben und in MySQL 5.1 bleiben möchten, installieren Sie das InnoDB-Plugin. Auf diese Weise können Sie alle CPUs für InnoDB nutzen.

11
RolandoMySQLDBA

INT (2) verwendet immer noch 4 Bytes - vielleicht meinten Sie TINYINT UNSIGNED?

Wie viele verschiedene Werte in setno? Wenn es klein ist, wird der SCHLÜSSEL (setno) niemals verwendet. INSERTing muss diesen Index aktualisieren. Durch Entfernen des Schlüssels wird INSERT etwas beschleunigt.

CHAR (10) - Ist flag immer 10 Zeichen lang? Und in utf8? Vielleicht könnten Sie das Flag VARCHAR (10) CHARACTER SET ascii verwenden

Stapeln Sie Ihre Beilagen - 100 auf einmal laufen zehnmal so schnell. (Mehr als 100 werden immer weniger.)

Was ist der Wert von Autocommit? Wickeln Sie jedes INSERT in BEGIN ... COMMIT ein? Was ist der Wert von innodb_flush_log_at_trx_commit?

2
Rick James

Richten Sie eine Warteschlange ein. Die Anwendung schreibt jeweils 1 Zeile in eine Warteschlange und nimmt dann Zeilen heraus und fügt sie stapelweise in eine Datenbank ein, basierend auf der Anzahl der Zeilen, die seit dem letzten Einfügen vergangen sind.

Ich habe gesehen, wo das Stapeln der Einsätze 10.000 auf einmal am schnellsten ist, also müssten Sie testen, um einen Sweet Spot zu finden.

Sie können Ihr eigenes einfaches Warteschlangensystem erstellen oder ein vorhandenes verwenden. Hier einige Beispiele: HornetQ und File :: Queue . Hier ist ein Beitrag auf SE, in dem einige andere gute Optionen aufgelistet sind: Nachrichtenwarteschlangen in Perl, PHP, Python .

1
dabest1