"Copia su tabella tmp" estremamente lento


15

Questo è il mio esempio di query:

SELECT
    nickname, 
    CASE class_id
      WHEN 1 THEN 'Druid'
      WHEN 2 THEN 'Necromancer'
      WHEN 3 THEN 'Mage'
      WHEN 4 THEN 'Priest'
      WHEN 5 THEN 'Warrior'
      WHEN 6 THEN 'Stalker'
      WHEN 7 THEN 'Paladin'
      WHEN 8 THEN 'Psionic'
    END class_name,
    ROUND(AVG(level),2) level,
    ROUND(AVG(tabard_id),2) tabard,
    CASE rank_id
      WHEN 1 THEN 'Leader'
      WHEN 2 THEN 'Officer'
      WHEN 3 THEN 'Veteran'
      WHEN 4 THEN 'HonoryMember'
      WHEN 5 THEN 'OrdinaryMember'
      WHEN 6 THEN 'Alt'
      WHEN 7 THEN 'Apprentice'
      WHEN 8 THEN 'Penalty'
    END rank_name,
    ROUND(AVG(loyality),2) loyality,
    ROUND((MAX(authority)-MIN(authority))/AVG(tabard_id)) authority_effective,
    MAX(authority)-MIN(authority) authority_delta,
    MIN(authority) authority_begin,
    MAX(authority) authority_end
FROM users
    LEFT JOIN level_history ON level_history.users_id = users.id
    LEFT JOIN tabard_history ON tabard_history.users_id = users.id
    LEFT JOIN rank_history ON rank_history.users_id = users.id
    LEFT JOIN loyality_history ON loyality_history.users_id = users.id
    LEFT JOIN authority_history ON authority_history.users_id = users.id
    LEFT JOIN guilds_has_users ON guilds_has_users.users_id = users.id
    LEFT JOIN report ON report.id = authority_history.report_id
      AND report.id = level_history.report_id
      AND report.id = loyality_history.report_id
      AND report.id = rank_history.report_id
      AND report.id = tabard_history.report_id
WHERE report.date BETWEEN '2011-10-24 00:00:00' AND '2011-10-30 23:59:59'
  AND guilds_has_users.active = 1
GROUP BY users.id;

Spiega che seleziona:

id  select_type   table               type    possible_keys                                            key                          key_len   ref                                           rows    Extra
1   SIMPLE        guilds_has_users    ref     fk_guilds_has_users_users1,active_IDX                    active_IDX                   1         const                                         139     Using where; Using temporary; Using filesort
1   SIMPLE        users               eq_ref  PRIMARY                                                  PRIMARY                      4         z92985_orlandino.guilds_has_users.users_id    1    
1   SIMPLE        level_history       ref     fk_level_history_users1,fk_level_history_report1,u...    fk_level_history_users1      4         z92985_orlandino.guilds_has_users.users_id    1       Using where
1   SIMPLE        report              eq_ref  PRIMARY,date_IDX,id_date_IDX                             PRIMARY                      4         z92985_orlandino.level_history.report_id      1       Using where
1   SIMPLE        tabard_history      ref     fk_tabard_history_users1,fk_tabard_history_report1...    fk_tabard_history_users1     4         z92985_orlandino.level_history.users_id       1       Using where
1   SIMPLE        rank_history        ref     fk_rank_history_users1,fk_rank_history_report1,use...    fk_rank_history_users1       4         z92985_orlandino.users.id                     1       Using where
1   SIMPLE        loyality_history    ref     fk_loyality_history_users1,fk_loyality_history_rep...    fk_loyality_history_users1   4         z92985_orlandino.rank_history.users_id        1       Using where
1   SIMPLE        authority_history   ref     fk_authority_history_users1,fk_authority_history_r...    fk_authority_history_users1  4         z92985_orlandino.level_history.users_id       1       Using where

La profilazione di quella selezione mi dice:

(139 total, Query took 4.4918 sec)
Copying to tmp table 4.488318

E alcune informazioni sulle variabili MySQL:

SHOW VARIABLES LIKE '%buffer%';

Variable_name              Value
bulk_insert_buffer_size    8388608
join_buffer_size           131072
key_buffer_size            12884901888
myisam_sort_buffer_size    8388608
net_buffer_length          16384
preload_buffer_size        32768
read_buffer_size           131072
read_rnd_buffer_size       25165824
sort_buffer_size           2097144
sql_buffer_result          OFF

Perché la copia su tabella tmp è così lenta? Come migliorare la velocità della mia query?

PS: Non riesco a configurare MySQL perché il mio provider di hosting non lo consentirà.

Risposte:


22

Potrebbe essere necessario provare a impostare determinate variabili all'interno della sessione

Questi valori particolari potrebbero essere troppo piccoli affinché la tua connessione DB possa soddisfare la query in modo efficiente. Questi possono essere impostati come segue:

  • Per vedere quali valori hanno attualmente queste impostazioni, procedi come segue:
    • SHOW VARIABLES LIKE 'max_heap_table_size';
    • SHOW VARIABLES LIKE 'tmp_table_size';
  • Per impostare max_heap_table_size su 64M, procedi come segue:
    • SET max_heap_table_size = 1024 * 1024 * 64;
  • Per impostare tmp_table_size su 32M, procedi come segue:
    • SET tmp_table_size = 1024 * 1024 * 32;

Si prega di consultare il documentazione MySQL sull'uso della tabella temporanea

Se non riesci a impostare questi valori nella tua sessione, contatta il tuo provider di hosting per impostarli dinamicamente in my.cnf.

Provaci !!!


+1 per l'impostazione delle variabili all'interno della sessione, può sicuramente aiutare questa query, che sembra piuttosto complicata ...
Dave Rix,

5

È possibile ridurre la query solo a quelle tabelle assolutamente necessarie per produrre l'output oppure suddividere la query in più query separate per estrarre parti diverse delle informazioni?

Potresti scoprire che eseguire tre query separate sui tuoi dati sarà più rapido rispetto a eseguirne uno enorme, specialmente quando il tuo database inizia a crescere fino a decine e centinaia di migliaia di righe.

Ho anche notato dal mio lavoro che le LEFT JOINquery non sono necessariamente le più efficienti, quindi usale solo quando assolutamente necessario ...

Spero possa aiutare :)


1
A volte le query più piccole rendono più senso di una massa ondeggiante di tavoli e LEFT unisce (Esempio: stackoverflow.com/questions/5983156/... ) +1 !!!
RolandoMySQLDBA
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.