"Copiar a la tabla tmp" extremadamente lento

15

Este es mi ejemplo de consulta:

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;

Explicar de ese selecto:

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

El perfil de ese select me dice:

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

Y alguna información sobre las variables de 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

¿Por qué es tan lento copiar a la tabla tmp? ¿Cómo mejorar la velocidad de mi consulta?

PD: No puedo configurar MySQL porque mi proveedor de hosting no lo permite.

Gofrolist
fuente

Respuestas:

22

Es posible que deba intentar establecer ciertas variables dentro de su sesión

Estos valores particulares pueden ser demasiado pequeños para que su conexión de base de datos satisfaga la consulta de manera eficiente. Estos se pueden configurar de la siguiente manera:

  • Para ver qué valores tiene actualmente esta configuración, haga lo siguiente:
    • SHOW VARIABLES LIKE 'max_heap_table_size';
    • SHOW VARIABLES LIKE 'tmp_table_size';
  • Para establecer max_heap_table_size en 64M, haga lo siguiente:
    • SET max_heap_table_size = 1024 * 1024 * 64;
  • Para establecer tmp_table_size en 32M, haga lo siguiente:
    • SET tmp_table_size = 1024 * 1024 * 32;

Consulte la documentación de MySQL sobre el uso de la tabla temporal

Si no puede establecer estos valores dentro de su propia sesión, póngase en contacto con su proveedor de alojamiento para configurarlos dinámicamente en su my.cnf.

Darle una oportunidad !!!

RolandoMySQLDBA
fuente
+1 para configurar las variables dentro de la sesión, ciertamente puede ayudar a esta consulta, que parece bastante complicada ...
Dave Rix
5

¿Puede reducir la consulta solo a esas tablas absolutamente necesarias para producir su salida, o dividir la consulta en múltiples consultas separadas para extraer diferentes partes de la información?

Es muy posible que ejecute tres consultas separadas en sus datos será más rápido que ejecutar una enorme, especialmente cuando su base de datos comienza a crecer a decenas y cientos de miles de filas.

También he notado por mi propio trabajo que las LEFT JOINconsultas no son necesariamente las más eficientes, así que solo úselas cuando sea absolutamente necesario ...

Espero que ayude :)

Dave Rix
fuente
1
A veces, las consultas más pequeñas tienen más sentido que una gran cantidad de tablas y uniones IZQUIERDA (Ejemplo: stackoverflow.com/questions/5983156/… ) +1 !!!
RolandoMySQLDBA