La table InnoDB lourde d'insertion n'utilise pas tout mon processeur

8

J'ai une base de données de journaux de paquets, qui n'est presque jamais interrogée. Il doit juste être rapide sur les inserts. J'utilise InnoDB parce que je voudrais maintenir la conformité ACID, car même la perte d'un seul paquet pourrait être préjudiciable à nos clients. Dans un scénario d'optimisation des performances, j'envoie 1 000 000 de paquets au serveur via plusieurs connexions DB. Mais quels que soient les paramètres que j'utilise dans my.cnf, je n'arrive pas à faire en sorte que le processus mysqld utilise plus de 900% de CPU sur un système à 12 cœurs. (Rien d'autre ne tourne sur la boîte.)

J'ai réglé ce qui suit

  • innodb_file_per_table = 1
  • innodb_write_io_threads = 64
  • innodb_read_io_threads = 64
  • innodb_thread_concurrency = 0

Si j'utilise MyISAM, je peux obtenir tous les paquets écrits en environ 6 secondes. Mais InnoDB en prend environ 25. Puis-je faire en sorte que MySQL utilise le reste des ressources système et l'insère plus rapidement?

Edit: Voici le schéma de la table:

+-------+----------------------+------+-----+---------+-------+
| Field | Type                 | Null | Key | Default | Extra |
+-------+----------------------+------+-----+---------+-------+
| t     | bigint(20) unsigned  | YES  |     | NULL    |       |
| a     | char(1)              | YES  |     | NULL    |       |
| sa    | int(10) unsigned     | YES  |     | NULL    |       |
| sb    | int(10) unsigned     | YES  |     | NULL    |       |
| sc    | int(10) unsigned     | YES  |     | NULL    |       |
| sd    | int(10) unsigned     | YES  |     | NULL    |       |
| sp    | smallint(5) unsigned | YES  |     | NULL    |       |
| da    | int(10) unsigned     | YES  |     | NULL    |       |
| db    | int(10) unsigned     | YES  |     | NULL    |       |
| dc    | int(10) unsigned     | YES  |     | NULL    |       |
| dd    | int(10) unsigned     | YES  |     | NULL    |       |
| dp    | smallint(5) unsigned | YES  |     | NULL    |       |
+-------+----------------------+------+-----+---------+-------+

edit2: J'ai regroupé plusieurs insertions afin qu'une seule requête soit proche de la longueur maximale (environ 16 000 000 de caractères). La base de données atteint désormais 1100% pendant deux secondes, puis descend à 100% le reste du temps. Le temps total est maintenant de 21 secondes, soit environ 16% plus rapide que lorsque j'ai commencé.

sep332
la source

Réponses:

7

Vous devez également augmenter innodb_io_capacity .

La valeur par défaut est 200. Augmentez-la à 5000 pour commencer. J'irais au 20000.

Vous pouvez également vous en assurer ib_logfile0et ib_logfile1être suffisamment grand. La valeur par défaut pour innodb_log_file_size est 5M. Je voudrais porter cela à 1G pour commencer.

Un pool de tampons InnoDB plus important serait également utile, peut-être 4G.

Pour récapituler, utilisez ces paramètres supplémentaires:

[mysqld]
innodb_io_capacity=5000
innodb_buffer_pool_size=4G
innodb_log_file_size=1G

Après avoir ajouté ces paramètres à my.cnf, pour redimensionner ib_logfile0 / ib_logfile1, procédez comme suit

service mysql stop
rm -f /var/log/mysql/ib_logfile[01]
service mysql start

Les fichiers ib_logfile0 et ib_logfile1 sont recréés. Ne vous inquiétez pas, je l'ai fait plusieurs fois .

Vous devrez peut-être faire quelque chose hors de l'ordinaire pour InnoDB

Essayez ce qui suit:

  • Verrou de table complet sur la table InnoDB
  • Effectuer le chargement en masse
  • Relâchez le verrou
RolandoMySQLDBA
la source
Serait-il utile d'avoir plusieurs pools de mémoire tampon? Ou comme il ne s'agit que d'une seule table, est-ce important?
sep332
Un seul pool de tampons. De cette façon, il n'y a pas de limite virtuelle. J'ai un client qui a MySQL 5.5.9 en utilisant un seul pool de mémoire tampon de 162 Go et il fonctionne très bien.
RolandoMySQLDBA
En utilisant cela, j'ai atteint environ 950% du processeur, mais cela ne semble pas être plus rapide.
sep332
Essayez un verrouillage complet de la table sur la table InnoDB avant le chargement en bloc.
RolandoMySQLDBA
3

Un certain nombre de facteurs ont une incidence sur la capacité de maximiser l'utilisation de plusieurs cœurs.

  • Certains mutex affecteront plusieurs processeurs, laissant certains en attente avant de pouvoir continuer.
  • Vous avez besoin d'autant de threads actifs que de processeurs. Si votre charge de travail se traduit par 9 threads parallèles, vous ne pouvez pas remplir 12 cœurs.
  • La capacité d'E / S doit être suffisante pour fournir suffisamment de travail à tous les processeurs. Si vous êtes en file d'attente sur les E / S disque ou en attente de messages réseau, vous ne pourrez pas remplir les CPU.

Des outils comme le SAR vous permettront de déterminer s'il existe des goulots d'étranglement qui réduisent votre capacité. Soyez simplement averti, l'élimination d'un goulot d'étranglement, ne fera que déplacer le goulot d'étranglement.

BillThor
la source