MySQL Slow Writes

8

Das Einfügen in die folgende Tabelle dauert bis zu 70 Sekunden:

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Die Tabelle enthält ungefähr 100.000 Zeilen und benötigt 7 MB auf der Festplatte.

Gibt es einige Einstellungen in MySQL, die die Schreibleistung verbessern können?

Meine my.cnfDatei lautet wie folgt:

log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1 
log-queries-not-using-indexes

innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT

query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800

sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M

read_buffer_size=128K

open_files_limit               = 1000
table_definition_cache         = 1024
table_open_cache               = 6000

max_heap_table_size=512M
tmp_table_size=4096M

max_connections=1000

thread_concurrency = 24

Hier ist das Hardware-Setup:

  • Dell R710
  • RAID10
  • 48G RAM

Angesichts dieser Hardware würde ich nicht erwarten, dass das Problem ein Hardware-Engpass ist.

Ronn0
quelle
Können Sie objektive Daten angeben? Protokolle, Ihre Test- / Benchmarking-Methode und Ergebnisse, so etwas?
Womble
Welche Art von Protokollen möchten Sie sehen? Das einzige, was ich sehe, warum es so lange dauert, ist in de mtop . Ich würde Dinge testen, wie die Tabelle in eine Myisam-Tabelle ändern, höhere Speichergrenzen, höhere Threads.
Ronn0
Die beste Einstellung, um MySQL zu verbessern ... ist, zu Postgres Lol zu wechseln
Antony Gibbs
thread_concurrency = 24 hat keine Auswirkung ... Sie können diese Zeile ausgeben
Antony Gibbs

Antworten:

16

BEOBACHTUNG # 1

Das allererste, was mir auffällt, ist die Tischstruktur

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Bitte beachten Sie, dass der categoriesIdIndex und der PRIMARY KEY mit derselben Spalte beginnen. Es ist ein redundanter Index. Da es sich bei dieser Tabelle um InnoDB handelt, ist der categoriesIdIndex aus einem anderen Grund redundant: Alle Sekundärindizes enthalten Schlüssel für gen_clust_index (auch bekannt als Clustered Index; siehe, wofür wird gen_clust_index in MySQL verwendet? ).

Wenn Sie den categoriesIdIndex mit entfernen

ALTER TABLE productsCategories DROP INDEX categoriesId;

Dies wird INSERTs dramatisch verbessern, da keine zusätzliche Wartung des Sekundär- und Clustered-Index durchgeführt werden muss.

BEOBACHTUNG # 2

Wenn Sie Masseneinfügevorgänge ausführen, benötigen Sie einen großen Masseneinfügepuffer .

Bitte beachten Sie meine bisherigen Beiträge dazu:

BEOBACHTUNG # 3

Ihre Protokolldatei ist viel zu klein !!! Es sollte 25% des InnoDB-Pufferpools sein, in Ihrem Fall sollte es 1G sein. In meinem Beitrag erfahren Sie, wie Sie die Größe von InnoDB-Protokolldateien ändern können .

BEOBACHTUNG # 4

Bitte nicht innodb_thread_concurrency setzen !!! Ich habe bei Percona Live NYC aus erster Hand gelernt, diese Einstellung in Ruhe zu lassen . Es ist in MySQL 5.5, MySQL 5.1 InnoDB Plugin und Percona Server 5.1+ standardmäßig deaktiviert.

BEOBACHTUNG # 5

Sie müssen innodb_file_per_table verwenden. Wenn dies deaktiviert ist, mache ich die Dateiverwaltung auf ibdata1 zu einem Albtraum. Bitte lesen Sie meinen Beitrag darüber, wie Sie InnoDB bereinigen können, um dies zu implementieren .

BEOBACHTUNG # 6

Wenn Sie MySQL 5.5 oder Percona Server verwenden, müssen Sie bestimmte Optionen festlegen, damit InnoDB mehrere CPUs / mehrere Kerne verwendet. Bitte lesen Sie meinen Beitrag zu diesen Einstellungen .

BEOBACHTUNG # 7

Du hast innodb_log_buffer_size=4M. Der Standardwert ist 8M. Dadurch werden die Redo-Protokolle doppelt so häufig gespült. Das wirkt auch Ihrer innodb_flush_log_at_trx_commit=2Einstellung entgegen . Bitte stellen Sie es auf 32M ein. Weitere Informationen finden Sie in der MySQL-Dokumentation zu innodb_log_buffer_size .

In Anbetracht dieser Beobachtungen fügen Sie bitte die folgenden Einstellungen hinzu oder ersetzen Sie sie:

[mysqld]
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000
innodb_file_per_table
innodb_log_file_size=1G
innodb_log_buffer_size=1G
bulk_insert_buffer_size = 256M
RolandoMySQLDBA
quelle
Wow, danke! Ich habe alle Punkte gedruckt und jetzt daran gearbeitet und sie im Gehirn gespeichert, um anderen Menschen in Zukunft zu helfen. Danke vielmals!
Ronn0
2
query_cache_sizeist auch enorm. Für jede Einfügung müssen bis zu 6 GB Cache geleert werden.
Aaron Brown
@ AaronBrown Ich stimme zu. Ich habe im High Performance MySQL-Buch gelesen, dass InnoDB mühsame Dinge mit der Transaktions-ID in der InnoDB-Tabelle im Abfrage-Cache erledigt, was es unnötig macht, einen Abfrage-Cache zu verwenden, ganz zu schweigen von der Langsamkeit. In MySQL 4.1 ist der Abfragecache für InnoDB deaktiviert.
RolandoMySQLDBA
Ich denke, der Abfrage-Cache ist völlig unabhängig von der Speicher-Engine. Grundsätzlich werden alle Schreibvorgänge serialisiert, indem alles gezwungen wird, den Abfragecache nach ungültigen Abfragen zu durchsuchen. Ich habe nie einen Anwendungsfall dafür gefunden und es hat immer Probleme verursacht.
Aaron Brown
noch etwas hinzuzufügen: query_cache_size = 6G <- das ist absolut absurd. Der Abfrage-Cache ist häufig besser deaktiviert und sollte auf keinen Fall größer als 32M oder 64M sein. Der Aufwand für die Verwaltung eines 6G-Abfragecaches beeinträchtigt sicherlich die Leistung.
Gavin Towey
0

Sie sollten überprüfen innodb_log_file_size, ob die Standardeinstellung 5 MB ist, was für schreibintensive Setups recht niedrig ist. Stellen Sie es auf 100M ein. Sie müssen die alten ib_logfile*Dateien löschen , um die Datenbank mit neuen Einstellungen zu starten. Bitte löschen Sie die Protokolldateien nicht, während der DB-Server ausgeführt wird. Sie müssen ihn zuerst stoppen. Wahrscheinlich sollten Sie zuerst die alten Protokolldateien sichern und nicht nur löschen.

Alex
quelle