"In tmp-Tabelle kopieren" ist extrem langsam

15

Dies ist mein Beispiel für eine Abfrage:

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;

Erklären Sie dies mit select:

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

Das Profiling dieser Auswahl sagt mir:

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

Und ein paar Informationen zu MySQL-Variablen:

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

Warum ist das Kopieren in die tmp-Tabelle so langsam? Wie kann ich die Geschwindigkeit meiner Abfrage verbessern?

PS: Ich kann MySQL nicht konfigurieren, da mein Hosting-Provider dies nicht zulässt.

Gofrolist
quelle

Antworten:

22

Möglicherweise müssen Sie versuchen, bestimmte Variablen in Ihrer Sitzung festzulegen

Diese bestimmten Werte sind möglicherweise zu klein, als dass Ihre DB-Verbindung die Abfrage effizient ausführen könnte. Diese können wie folgt eingestellt werden:

  • Um zu sehen, welche Werte diese Einstellungen aktuell haben, gehen Sie wie folgt vor:
    • SHOW VARIABLES LIKE 'max_heap_table_size';
    • SHOW VARIABLES LIKE 'tmp_table_size';
  • Gehen Sie wie folgt vor, um max_heap_table_size auf 64 MB festzulegen:
    • SET max_heap_table_size = 1024 * 1024 * 64;
  • Gehen Sie folgendermaßen vor, um tmp_table_size auf 32M festzulegen:
    • SET tmp_table_size = 1024 * 1024 * 32;

Bitte konsultieren Sie die MySQL-Dokumentation zur Verwendung der temporären Tabellen

Wenn Sie diese Werte in Ihrer eigenen Sitzung nicht festlegen können, wenden Sie sich an Ihren Hosting-Anbieter, um sie dynamisch in Ihrer my.cnf festzulegen.

Versuche es !!!

RolandoMySQLDBA
quelle
+1 für das Setzen der Variablen innerhalb der Sitzung, kann es sicherlich helfen, diese Abfrage, die ziemlich kompliziert aussieht ...
Dave Rix
5

Können Sie die Abfrage möglicherweise auf nur die Tabellen reduzieren, die für die Ausgabe unbedingt erforderlich sind, oder die Abfrage in mehrere separate Abfragen aufteilen, um verschiedene Teile der Informationen abzurufen?

Sie werden feststellen, dass das Ausführen von drei separaten Abfragen für Ihre Daten schneller ist als das Ausführen einer großen Abfrage - insbesondere, wenn Ihre Datenbank auf Zehntausende von Zeilen angewachsen ist.

Das habe ich auch aus meiner eigenen Arbeit mitbekommen LEFT JOIN Abfragen nicht unbedingt die effizientesten sind, also verwenden Sie sie nur, wenn es absolut notwendig ist ...

Ich hoffe, das hilft :)

Dave Rix
quelle
1
Manchmal sind kleinere Abfragen sinnvoller als eine große Menge von Tabellen und LEFT JOINs (Beispiel: stackoverflow.com/questions/5983156/… ) +1 !!!
RolandoMySQLDBA