CREATE TABLE AS SELECT élimant MySQL
-
06-07-2019 - |
Question
Nous utilisons un serveur MySQL avec une charge modérée (200-300 QPS) sur un matériel assez puissant (HP DL360 avec 8 cœurs Xeon, 8 Go de RAM et RAID10). Toutes les tables sont innodb et l’ensemble de données actif s’inscrit dans le alloué innodb_buffer_pool_size
.
Notre base de données est normalisée et afin de réduire le nombre de jointures, nous utilisons des vues matérialisées pour aplatir l'ensemble de données. Lorsque les données sont ajoutées par lots plusieurs fois par jour, les MV: sont régénérés à l'aide de CREATE TABLE AS SELECT
au lieu d'être mis à jour de manière dynamique à l'aide de déclencheurs complexes.
Le problème est que parfois, alors que ces requêtes CREATE
sont exécutées (chacune d’elles prend entre 5 et 50 secondes), d’autres requêtes non liées au serveur semblent se mettre en file d'attente derrière le CREATE
requête menant à une base de données ne répondant pas.
Pour (re) générer le MV: nous utilisons quelque chose comme ceci:
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;
L’EXPLAIN du SELECT produit quelque chose comme:
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
| 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 */
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
Des idées pour lesquelles le CREATE TABLE AS
surcharge complètement notre serveur et comment puis-je l’empêcher?
Cordialement,
La solution
Nous avons résolu ce problème en basculant vers SELECT INTO et LOAD DATA INFILE comme suit: http://www.mysqlperformanceblog.com/2006/07/12/insert-into-select-performance-with-innodb-tables/ . Un grand merci à Randolph Potter pour nous avoir envoyé dans la bonne direction.
Autres conseils
Cela pourrait-il être la cause?
Remarque: DROP TABLE valide automatiquement la transaction active en cours, sauf si vous utilisez le mot clé TEMPORARY.
( http://dev.mysql.com/ doc / refman / 5.1 / fr / drop-table.html )