La tabla InnoDB de inserción pesada no usará toda mi CPU

8

Tengo una base de datos de registro de paquetes, que casi nunca se consulta. Solo necesita ser rápido en los insertos. Estoy usando InnoDB porque me gustaría mantener el cumplimiento de ACID, ya que incluso perder un solo paquete podría ser perjudicial para nuestros clientes. En un escenario de ajuste de rendimiento, envío 1,000,000 de paquetes al servidor a través de múltiples conexiones de base de datos. Pero no importa qué configuración use en my.cnf, no puedo lograr que el proceso mysqld use más del 900% de CPU en un sistema con 12 núcleos. (Nada más se está ejecutando en la caja).

He establecido lo siguiente

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

Si uso MyISAM, puedo obtener todos los paquetes escritos en aproximadamente 6 segundos. Pero InnoDB toma alrededor de 25. ¿Puedo hacer que MySQL use el resto de los recursos del sistema e inserte más rápido?

Editar: Aquí está el esquema de la tabla:

+-------+----------------------+------+-----+---------+-------+
| 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: He agrupado más inserciones para que una sola consulta esté cerca de la longitud máxima (aproximadamente 16,000,000 caracteres). La base de datos ahora aumenta al 1100% durante dos segundos, luego baja al 100% por el resto del tiempo. El tiempo total ahora es de 21 segundos, o aproximadamente un 16% más rápido que cuando comencé.

sep332
fuente

Respuestas:

7

Tienes que poner en marcha innodb_io_capacity también.

El valor predeterminado es 200. Elevarlo a 5000 para empezar. Yo iría a 20000.

Es posible que también desee asegurarse ib_logfile0y que ib_logfile1sean lo suficientemente grandes. El valor predeterminado para innodb_log_file_size es 5M. Yo elevaría eso a 1G para empezar.

Un grupo de búferes InnoDB más grande también ayudaría, quizás 4G.

Para recapitular, use estas configuraciones adicionales:

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

Después de agregar esta configuración a my.cnf, para cambiar el tamaño de ib_logfile0 / ib_logfile1, haga lo siguiente

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

Los archivos ib_logfile0 e ib_logfile1 se recrean. No te preocupes, he hecho esto muchas veces .

Puede que tenga que hacer algo fuera de lo común para InnoDB

Intenta lo siguiente:

  • Full Table Lock en la mesa InnoDB
  • Realizar la carga masiva
  • Liberar el bloqueo
RolandoMySQLDBA
fuente
¿Sería útil tener varias agrupaciones de almacenamiento intermedio? O como es solo una mesa, ¿importaría?
sep332
Solo un grupo de búferes. De esa manera no hay límite virtual. Tengo un cliente que tiene MySQL 5.5.9 usando un único grupo de búfer de 162 GB y funciona de maravilla.
RolandoMySQLDBA
Con esto llegué a aproximadamente un 950% de CPU, pero no parece ser más rápido.
sep332
Pruebe con un bloqueo de tabla completo en la tabla InnoDB antes de la carga masiva.
RolandoMySQLDBA
3

Hay una serie de factores que afectan la capacidad de maximizar el uso de múltiples núcleos.

  • Algunos mutexes impactarán en múltiples CPU dejando algo de espera antes de que puedan continuar.
  • Necesita tantos subprocesos activos como CPU. Si su carga de trabajo da como resultado 9 hilos paralelos, no puede llenar 12 núcleos.
  • La capacidad de E / S debe ser suficiente para proporcionar suficiente trabajo para todas las CPU. Si está haciendo cola en el disco de E / S o esperando mensajes de red, entonces no podrá llenar las CPU.

Las herramientas como SAR le permitirán determinar si hay cuellos de botella que reducen su capacidad. Solo se advirtió, eliminando un cuello de botella, solo moverá el cuello de botella.

BillThor
fuente