"Menyalin ke tabel tmp" sangat lambat

15

Ini adalah contoh permintaan saya:

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;

Jelaskan pilihan itu:

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

Profiling yang pilih memberitahu saya:

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

Dan beberapa informasi tentang variabel 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

Mengapa menyalin ke tabel tmp sangat lambat? Bagaimana cara meningkatkan kecepatan permintaan saya?

PS: Saya tidak bisa mengkonfigurasi MySQL karena penyedia hosting saya tidak mengizinkannya.

Gofrolist
sumber

Jawaban:

22

Anda mungkin perlu mencoba mengatur variabel tertentu dalam sesi Anda

Nilai-nilai khusus ini mungkin terlalu kecil untuk Koneksi DB Anda untuk memenuhi permintaan secara efisien. Ini dapat diatur dalam sebagai berikut:

  • Untuk melihat nilai apa yang telah dilakukan oleh pengaturan ini, lakukan hal berikut:
    • SHOW VARIABLES LIKE 'max_heap_table_size';
    • SHOW VARIABLES LIKE 'tmp_table_size';
  • Untuk mengatur max_heap_table_size ke 64M lakukan hal berikut:
    • SET max_heap_table_size = 1024 * 1024 * 64;
  • Untuk mengatur tmp_table_size ke 32M lakukan hal berikut:
    • SET tmp_table_size = 1024 * 1024 * 32;

Silakan baca Dokumentasi MySQL tentang Penggunaan Tabel Temp

Jika Anda tidak dapat menetapkan nilai-nilai ini dalam sesi Anda sendiri, hubungi penyedia hosting Anda untuk secara dinamis mengaturnya di my.cnf Anda.

Cobalah !!!

RolandoMySQLDBA
sumber
+1 untuk menyetel variabel dalam sesi, tentu dapat membantu kueri ini, yang terlihat agak rumit ...
Dave Rix
5

Bisakah Anda mengurangi kueri menjadi hanya tabel yang benar-benar diperlukan untuk menghasilkan output, atau memecah kueri menjadi beberapa kueri terpisah untuk mengeluarkan berbagai bagian informasi?

Anda mungkin menemukan bahwa menjalankan tiga kueri terpisah pada data Anda akan lebih cepat daripada menjalankan satu kueri besar - terutama ketika basis data Anda mulai tumbuh hingga puluhan dan ratusan ribu baris.

Saya juga telah memperhatikan dari pekerjaan saya sendiri bahwa LEFT JOINpermintaan belum tentu yang paling efisien, jadi gunakan saja ketika benar-benar diperlukan ...

Semoga itu bisa membantu :)

Dave Rix
sumber
1
Terkadang, kueri yang lebih kecil lebih masuk akal daripada tumpukan tabel dan LEFT JOINs (Contoh: stackoverflow.com/questions/5983156/… ) +1 !!!
RolandoMySQLDBA