CREAR TABLA COMO SELECCIONAR matando MySQL
-
06-07-2019 - |
Pregunta
Ejecutamos un servidor MySQL con carga moderada (200-300 QPS) en hardware bastante potente (HP DL360 con 8 núcleos Xeon, 8Gb RAM y RAID10). Todas las tablas son innodb y el conjunto de datos activo se ajusta dentro del innodb_buffer_pool_size
asignado.
Nuestra base de datos está normalizada y para reducir el número de uniones usamos vistas materializadas para aplanar el conjunto de datos. A medida que los datos se agregan en lotes varias veces al día, los MV: s se regeneran usando CREATE TABLE AS SELECT
en lugar de actualizarse dinámicamente usando activadores complejos.
El problema es que a veces, mientras se ejecutan estas consultas CREATE
(cada una de las cuales toma de 5 a 50 segundos), otras consultas no relacionadas con el servidor parecen estar en cola detrás de CREATE
consulta, que conduce a una base de datos que no responde.
Para (re) generar los MV: s usamos algo como esto:
BEGIN TRANSACTION;
DROP TABLE IF EXISTS TableName_TMP;
CREATE TABLE TableName_TMP ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_swedish_ci AS
SELECT about100columns, and10Expressions
FROM Table1
JOIN Table2 ON Table1.fk = Table2.pk
/* join up to 13 other tables */
WHERE ((removed IS NULL OR removed = 0))
ORDER BY created DESC, id ASC;
ALTER TABLE TableName_TMP ADD PRIMARY KEY(id), INDEX(created);
DROP TABLE IF EXISTS TableName;
ALTER TABLE TableName_TMP RENAME TO TableName;
COMMIT;
La EXPLICACIÓN de SELECT produce algo como:
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+-------------+---------------+------------+---------+ ------------------------------+-------+-----------------------------+
| 1 | SIMPLE | Table1 | ref_or_null | removed | removed | 5 | const | 76093 | Using where; Using filesort |
| 1 | SIMPLE | Table2 | eq_ref | PRIMARY | PRIMARY | 4 | Table1.fk1 | 1 | |
| 1 | SIMPLE | Table3 | eq_ref | PRIMARY | PRIMARY | 4 | Table1.fk2 | 1 | |
/* More of the same */
| 1 | SIMPLE | TableN | eq_ref | PRIMARY | PRIMARY | 4 | TableM.fk | 1 | Using index |
| 1 | SIMPLE | TableX | eq_ref | PRIMARY | PRIMARY | 4 | TableY.fk | 1 | |
/* More of the same */
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
¿Alguna idea de por qué CREATE TABLE AS
sobrecarga completamente nuestro servidor y cómo puedo evitarlo?
Saludos,
Solución
Resolvimos esto cambiando a SELECT INTO y LOAD DATA INFILE como http://www.mysqlperformanceblog.com/2006/07/12/insert-into-select-performance-with-innodb-tables/ . Muchas gracias a Randolph Potter por enviarnos en la dirección correcta.
Otros consejos
¿Podría ser esta la causa?
Nota: DROP TABLE confirma automáticamente la transacción activa actual, a menos que use la palabra clave TEMPORAL.
( http://dev.mysql.com/ doc / refman / 5.1 / es / drop-table.html )