Escrituras lentas de MySQL

8

Las inserciones en la siguiente tabla tardan hasta 70 segundos en completarse:

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;

Hay alrededor de 100,000 filas en la tabla, y está tomando 7MB en el disco.

¿Hay algunas configuraciones en MySQL que pueden mejorar el rendimiento de escritura?

Mi my.cnfarchivo es el siguiente:

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

Aquí está la configuración de hardware:

  • Dell R710
  • RAID10
  • 48G RAM

Dado este hardware, no esperaría que el problema sea un cuello de botella de hardware.

Ronn0
fuente
¿Puedes proporcionar algunos datos objetivos? ¿Registros, su metodología de pruebas / benchmarking y resultados, ese tipo de cosas?
womble
¿Qué tipo de registros te gustaría ver? Lo único que veo por qué tarda tanto es en mtop . Probaría cosas como cambiar la tabla a una tabla myisam, límites de memoria más altos, hilos más altos.
Ronn0
La mejor configuración para mejorar mysql ... es cambiar a postgres lol
Antony Gibbs
thread_concurrency = 24 no tiene efecto ... puedes volcar esa línea
Antony Gibbs

Respuestas:

16

OBSERVACIÓN # 1

Lo primero que me llama la atención es la estructura de la mesa.

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;

Tenga en cuenta que el categoriesIdíndice y la CLAVE PRIMARIA comienzan con la misma columna. Es un índice redundante. Dado que esta tabla es InnoDB, el categoriesIdíndice es redundante por otra razón: todos los índices secundarios contienen claves en gen_clust_index (también conocido como Clustered Index; ¿para qué se utiliza gen_clust_index en mysql? )

Si elimina el categoriesIdíndice con

ALTER TABLE productsCategories DROP INDEX categoriesId;

esto mejorará los INSERT drásticamente debido a que no es necesario realizar un mantenimiento de índice secundario y en clúster adicional.

OBSERVACIÓN # 2

Si está realizando operaciones de inserción masiva, necesita un búfer de inserción masiva grande .

Por favor, vea mis publicaciones anteriores sobre esto:

OBSERVACIÓN # 3

¡El tamaño de su archivo de registro es demasiado pequeño! Debería ser el 25% del InnoDB Buffer Pool, que en su caso debería ser 1G. Vea mi publicación sobre cómo cambiar el tamaño de los archivos de registro de InnoDB .

OBSERVACIÓN # 4

Por favor, no establezca innodb_thread_concurrency !!! Aprendí de primera mano en Percona Live NYC para dejar ese ambiente solo . Está deshabilitado de forma predeterminada en MySQL 5.5, MySQL 5.1 InnoDB Plugin y Percona Server 5.1+.

OBSERVACIÓN # 5

Necesita usar innodb_file_per_table. Si esto está deshabilitado, hago que el mantenimiento de archivos en ibdata1 sea una pesadilla. Lea mi publicación sobre cómo limpiar InnoDB para implementar esto .

OBSERVACIÓN # 6

Si está utilizando MySQL 5.5 o el Servidor Percona, debe establecer ciertas opciones para que InnoDB use múltiples CPU / núcleos múltiples. Por favor, vea mi publicación sobre esa configuración .

OBSERVACIÓN # 7

Usted tiene innodb_log_buffer_size=4M. El valor predeterminado es 8M. Eso provocará el doble de enrojecimiento en los registros de rehacer. Eso también contrarrestará su innodb_flush_log_at_trx_commit=2entorno. Por favor configúrelo en 32M. Además, consulte la documentación de MySQL en innodb_log_buffer_size .

A la luz de estas observaciones, agregue o reemplace las siguientes configuraciones:

[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
fuente
¡Wow gracias! Imprimí todos los puntos y trabajé en ellos ahora y los guardé en el cerebro para ayudar a otras personas en el futuro. ¡Muchas gracias!
Ronn0
2
query_cache_sizeTambién es enorme. Cada inserto requerirá que se vacíen hasta 6 GB de caché.
Aaron Brown
@AaronBrown Estoy de acuerdo. Leí en el libro MySQL de alto rendimiento que InnoDB hace cosas tediosas con el ID de transacción en la tabla InnoDB en la caché de consultas, lo que hace innecesario, por no mencionar lento, usar una caché de consultas. De hecho, MySQL 4.1 tiene el caché de consultas deshabilitado para InnoDB.
RolandoMySQLDBA
Creo que el caché de consultas está completamente separado del motor de almacenamiento. Básicamente, serializa todas las operaciones de escritura al obligar a todo a pasar y escanear el caché de consultas en busca de consultas para invalidar. Nunca he encontrado un caso de uso y siempre ha causado problemas.
Aaron Brown
Una cosa más para agregar: query_cache_size = 6G <- esto es total y absolutamente absurdo. La memoria caché de consultas a menudo se desactiva mejor, y seguramente no debería ser más grande que 32M o 64M. La sobrecarga de mantener un caché de consultas 6G ciertamente está perjudicando el rendimiento.
Gavin Towey
0

Debe verificar innodb_log_file_size, la configuración predeterminada es 5M, que es bastante baja para configuraciones de escritura intensiva. Considere configurarlo a 100M. Tendrá que eliminar los ib_logfile*archivos antiguos para iniciar la base de datos con la nueva configuración. No elimine los archivos de registro mientras se ejecuta el servidor de base de datos, primero deberá detenerlo. Probablemente primero deba hacer una copia de seguridad de los archivos de registro antiguos, no solo eliminarlos.

Alex
fuente