CREA TABELLA COME SELEZIONA uccidendo MySQL
-
06-07-2019 - |
Domanda
Eseguiamo un server MySQL con carico moderato (200-300 QPS) su hardware abbastanza potente (HP DL360 con 8 core Xeon, 8Gb RAM e RAID10). Tutte le tabelle sono innodb e il set di dati attivo rientra nel innodb_buffer_pool_size
.
Il nostro database è normalizzato e per ridurre il numero di join utilizziamo viste materializzate per appiattire il set di dati. Man mano che i dati vengono aggiunti in batch alcune volte al giorno, gli MV: vengono rigenerati utilizzando CREATE TABLE AS SELECT
anziché essere aggiornati dinamicamente utilizzando trigger complessi.
Il problema è che a volte mentre vengono eseguite queste query CREATE
(ognuna delle quali impiega dai 5 ai 50 secondi) altre query non correlate al server sembrano essere messe in coda dietro CREATE
, che porta a un database che non risponde.
Per (ri) generare il MV: s usiamo qualcosa del genere:
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;
EXPLAIN di SELECT produce qualcosa del tipo:
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
| 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 */
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
Qualche idea sul perché CREATE TABLE AS
sovraccarichi completamente il nostro server e come posso impedirlo?
Saluti,
Soluzione
Abbiamo risolto il problema passando a SELECT INTO e LOAD DATA INFILE come da http://www.mysqlperformanceblog.com/2006/07/12/insert-into-select-performance-with-innodb-tables/ . Mille grazie a Randolph Potter per averci inviato nella giusta direzione.
Altri suggerimenti
Potrebbe essere questa la causa?
Nota: DROP TABLE esegue automaticamente il commit della transazione attiva corrente, a meno che non si usi la parola chiave TEMPORARY.
( http://dev.mysql.com/ doc / refman / 5.1 / it / drop-table.html )