“复制到tmp表”非常慢


15

这是我的查询示例:

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;

说明选择的内容:

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

该选择的性能分析告诉我:

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

以及有关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

为什么复制到tmp表这么慢?如何提高查询速度?

PS:我无法配置MySQL,因为我的托管服务提供商不允许。

Answers:


22

您可能需要尝试在会话中设置某些变量

这些特定值可能太小,无法使您的数据库连接有效地执行查询。可以在以下范围内进行设置:

  • 若要查看这些设置当前具有什么值,请执行以下操作:
    • SHOW VARIABLES LIKE 'max_heap_table_size';
    • SHOW VARIABLES LIKE 'tmp_table_size';
  • 要将max_heap_table_size设置为64M,请执行以下操作:
    • SET max_heap_table_size = 1024 * 1024 * 64;
  • 要将tmp_table_size设置为32M,请执行以下操作:
    • SET tmp_table_size = 1024 * 1024 * 32;

请查阅有关临时表使用MySQL文档

如果您无法在自己的会话中设置这些值,请与您的主机提供商联系以在my.cnf中动态设置它们。

试试看 !!!


+1用于在会话中设置变量,它肯定可以帮助此查询,这看起来相当复杂...
Dave Rix

5

您是否可以将查询简化为仅生成输出所必需的那些表,或者将查询拆分为多个单独的查询以提取信息的不同部分?

您可能会发现,对数据运行三个单独的查询比运行一个庞大的查询要快-尤其是当数据库开始增长到成千上万的行时。

我还从自己的工作中注意到,LEFT JOIN查询不一定是最有效的,因此仅在绝对必要时才使用查询...

希望有帮助:)


1
有时,较小的查询比大量的表和LEFT JOIN有意义(示例:stackoverflow.com/questions/5983156/…)+1!
RolandoMySQLDBA 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.