2009-12-02 249 views
1

我想知道如何優化它,最好不改變表結構。如何優化這個慢速查詢?

SELECT p.author_id member_id, 
     m.members_display_name member_name, 
     COUNT(p.pid) posts 
FROM forum_topics t 
    STRAIGHT_JOIN forum_posts p 
    STRAIGHT_JOIN forum_members m 
WHERE p.author_id != 0 
     AND p.author_id = m.member_id 
     AND p.new_topic = 0 
     AND t.forum_id = 120 
     AND t.tid = p.topic_id 
GROUP BY p.author_id 
ORDER BY posts DESC 
LIMIT 1 

EXPLAIN輸出是:

------------------------------------------------------------------------------- 
EXPLAIN 
    SELECT p.author_id member_id, 
     m.members_display_name member_name, 
     COUNT(p.pid) posts 
    FROM forum_topics t 
     STRAIGHT_JOIN forum_posts p 
     STRAIGHT_JOIN forum_members m 
    WHERE p.author_id != 0 
     AND p.author_id = m.member_id 
     AND p.new_topic = 0 
     AND t.forum_id = 120 
     AND t.tid = p.topic_id 
GROUP BY p.author_id 
ORDER BY posts DESC 
    LIMIT 1\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: t 
     type: ref 
possible_keys: PRIMARY,forum_id,last_post 
      key: forum_id 
     key_len: 2 
      ref: const 
     rows: 28070 
     Extra: Using temporary; Using filesort 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: p 
     type: ref 
possible_keys: author_id,topic_id 
      key: topic_id 
     key_len: 4 
      ref: forumwmo.t.tid 
     rows: 5 
     Extra: Using where 
*************************** 3. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: m 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 3 
      ref: forumwmo.p.author_id 
     rows: 1 
     Extra: 
3 rows in set (0.00 sec) 

表的結構是:

SHOW CREATE TABLE forum_members\G 
*************************** 1. row *************************** 
     Table: forum_members 
Create Table: CREATE TABLE `forum_members` (
    `member_id` mediumint(8) NOT NULL AUTO_INCREMENT, 
    `name` varchar(32) NOT NULL DEFAULT '', 
    `member_group_id` smallint(3) NOT NULL DEFAULT '0', 
    `email` varchar(150) NOT NULL DEFAULT '', 
    `joined` int(10) NOT NULL DEFAULT '0', 
    `ip_address` varchar(16) NOT NULL DEFAULT '', 
    `posts` mediumint(7) DEFAULT '0', 
    `title` varchar(64) DEFAULT NULL, 
    `allow_admin_mails` tinyint(1) DEFAULT NULL, 
    `time_offset` varchar(10) DEFAULT NULL, 
    `hide_email` varchar(8) DEFAULT NULL, 
    `email_pm` tinyint(1) DEFAULT NULL, 
    `email_full` tinyint(1) DEFAULT NULL, 
    `skin` smallint(5) DEFAULT NULL, 
    `warn_level` int(10) DEFAULT NULL, 
    `warn_lastwarn` int(10) NOT NULL DEFAULT '0', 
    `language` varchar(32) DEFAULT NULL, 
    `last_post` int(10) DEFAULT NULL, 
    `restrict_post` varchar(100) NOT NULL DEFAULT '0', 
    `view_sigs` tinyint(1) DEFAULT '1', 
    `view_img` tinyint(1) DEFAULT '1', 
    `view_avs` tinyint(1) DEFAULT '1', 
    `view_pop` tinyint(1) DEFAULT '1', 
    `bday_day` int(2) DEFAULT NULL, 
    `bday_month` int(2) DEFAULT NULL, 
    `bday_year` int(4) DEFAULT NULL, 
    `msg_count_new` int(2) NOT NULL DEFAULT '0', 
    `msg_count_total` int(3) NOT NULL DEFAULT '0', 
    `msg_count_reset` int(1) NOT NULL DEFAULT '0', 
    `msg_show_notification` int(1) NOT NULL DEFAULT '0', 
    `misc` varchar(128) DEFAULT NULL, 
    `last_visit` int(10) DEFAULT '0', 
    `last_activity` int(10) DEFAULT '0', 
    `dst_in_use` tinyint(1) DEFAULT '0', 
    `view_prefs` varchar(64) DEFAULT '-1&-1', 
    `coppa_user` tinyint(1) DEFAULT '0', 
    `mod_posts` varchar(100) NOT NULL DEFAULT '0', 
    `auto_track` varchar(50) DEFAULT '0', 
    `org_perm_id` varchar(255) DEFAULT '', 
    `temp_ban` varchar(100) DEFAULT '0', 
    `sub_end` int(10) NOT NULL DEFAULT '0', 
    `no_sig_lims` tinyint(1) NOT NULL DEFAULT '0', 
    `login_anonymous` char(3) NOT NULL DEFAULT '0&0', 
    `ignored_users` text, 
    `mgroup_others` varchar(255) NOT NULL DEFAULT '', 
    `member_login_key` varchar(32) NOT NULL DEFAULT '', 
    `member_login_key_expire` int(10) NOT NULL DEFAULT '0', 
    `subs_pkg_chosen` smallint(3) NOT NULL DEFAULT '0', 
    `has_blog` tinyint(1) NOT NULL DEFAULT '0', 
    `members_auto_dst` tinyint(1) NOT NULL DEFAULT '1', 
    `members_cache` mediumtext, 
    `members_disable_pm` int(1) NOT NULL DEFAULT '0', 
    `members_display_name` varchar(255) NOT NULL DEFAULT '', 
    `members_seo_name` varchar(255) NOT NULL DEFAULT '', 
    `members_created_remote` tinyint(1) NOT NULL DEFAULT '0', 
    `members_editor_choice` char(3) NOT NULL DEFAULT 'std', 
    `members_profile_views` int(10) unsigned NOT NULL DEFAULT '0', 
    `members_l_display_name` varchar(255) NOT NULL DEFAULT '0', 
    `members_l_username` varchar(255) NOT NULL DEFAULT '0', 
    `failed_logins` text, 
    `failed_login_count` smallint(3) NOT NULL DEFAULT '0', 
    `has_gallery` int(1) DEFAULT '0', 
    `members_pass_hash` varchar(32) NOT NULL DEFAULT '', 
    `members_pass_salt` varchar(5) NOT NULL DEFAULT '', 
    `member_banned` tinyint(1) NOT NULL DEFAULT '0', 
    `identity_url` text, 
    `member_uploader` varchar(32) NOT NULL DEFAULT 'default', 
    `members_bitoptions` int(10) unsigned NOT NULL DEFAULT '0', 
    `fb_uid` bigint(20) NOT NULL DEFAULT '0', 
    `fb_emailhash` varchar(60) NOT NULL DEFAULT '', 
    `fb_emailallow` int(1) NOT NULL DEFAULT '0', 
    `fb_lastsync` int(10) NOT NULL DEFAULT '0', 
    `members_day_posts` varchar(32) NOT NULL DEFAULT '0,0', 
    `live_id` varchar(32) DEFAULT NULL, 
    PRIMARY KEY (`member_id`), 
    KEY `mgroup` (`member_group_id`), 
    KEY `bday_day` (`bday_day`), 
    KEY `bday_month` (`bday_month`), 
    KEY `members_l_display_name` (`members_l_display_name`), 
    KEY `members_l_username` (`members_l_username`), 
    KEY `member_banned` (`member_banned`), 
    KEY `members_bitoptions` (`members_bitoptions`), 
    KEY `ip_address` (`ip_address`) 
) ENGINE=MyISAM AUTO_INCREMENT=101965 DEFAULT CHARSET=latin1 
1 row in set (0.00 sec) 
------------------------------------------------------------------------------- 
SHOW CREATE TABLE forum_posts\G 
*************************** 1. row *************************** 
     Table: forum_posts 
Create Table: CREATE TABLE `forum_posts` (
    `append_edit` tinyint(1) DEFAULT '0', 
    `edit_time` int(10) DEFAULT NULL, 
    `pid` int(10) NOT NULL AUTO_INCREMENT, 
    `author_id` mediumint(8) NOT NULL DEFAULT '0', 
    `author_name` varchar(32) DEFAULT NULL, 
    `use_sig` tinyint(1) NOT NULL DEFAULT '0', 
    `use_emo` tinyint(1) NOT NULL DEFAULT '0', 
    `ip_address` varchar(16) NOT NULL DEFAULT '', 
    `post_date` int(10) DEFAULT NULL, 
    `icon_id` smallint(3) DEFAULT NULL, 
    `post` mediumtext, 
    `queued` tinyint(1) NOT NULL DEFAULT '0', 
    `topic_id` int(10) NOT NULL DEFAULT '0', 
    `post_title` varchar(255) DEFAULT NULL, 
    `new_topic` tinyint(1) DEFAULT '0', 
    `edit_name` varchar(255) DEFAULT NULL, 
    `post_parent` int(10) NOT NULL DEFAULT '0', 
    `post_key` varchar(32) NOT NULL DEFAULT '0', 
    `post_htmlstate` smallint(1) NOT NULL DEFAULT '0', 
    `post_edit_reason` varchar(255) NOT NULL DEFAULT '', 
    PRIMARY KEY (`pid`), 
    KEY `author_id` (`author_id`,`topic_id`), 
    KEY `post_date` (`post_date`), 
    KEY `topic_id` (`topic_id`,`queued`,`pid`,`post_date`), 
    KEY `post_key` (`post_key`), 
    KEY `ip_address` (`ip_address`) 
) ENGINE=MyISAM AUTO_INCREMENT=988489 DEFAULT CHARSET=latin1 
1 row in set (0.00 sec) 
------------------------------------------------------------------------------- 
SHOW CREATE TABLE forum_topics\G 
*************************** 1. row *************************** 
     Table: forum_topics 
Create Table: CREATE TABLE `forum_topics` (
    `tid` int(10) NOT NULL AUTO_INCREMENT, 
    `title` varchar(70) NOT NULL DEFAULT '', 
    `description` varchar(250) DEFAULT NULL, 
    `state` varchar(8) DEFAULT NULL, 
    `posts` int(10) DEFAULT NULL, 
    `starter_id` mediumint(8) NOT NULL DEFAULT '0', 
    `start_date` int(10) DEFAULT NULL, 
    `last_poster_id` mediumint(8) NOT NULL DEFAULT '0', 
    `last_post` int(10) DEFAULT NULL, 
    `icon_id` tinyint(2) DEFAULT NULL, 
    `starter_name` varchar(255) DEFAULT NULL, 
    `last_poster_name` varchar(255) DEFAULT NULL, 
    `poll_state` varchar(8) DEFAULT NULL, 
    `last_vote` int(10) DEFAULT NULL, 
    `views` int(10) DEFAULT '0', 
    `forum_id` smallint(5) NOT NULL DEFAULT '0', 
    `approved` tinyint(1) NOT NULL DEFAULT '0', 
    `author_mode` tinyint(1) DEFAULT NULL, 
    `pinned` tinyint(1) NOT NULL DEFAULT '0', 
    `moved_to` varchar(64) DEFAULT NULL, 
    `total_votes` int(5) NOT NULL DEFAULT '0', 
    `topic_hasattach` smallint(5) NOT NULL DEFAULT '0', 
    `topic_firstpost` int(10) NOT NULL DEFAULT '0', 
    `topic_queuedposts` int(10) NOT NULL DEFAULT '0', 
    `topic_rating_total` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `topic_rating_hits` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `topic_open_time` int(10) NOT NULL DEFAULT '0', 
    `topic_close_time` int(10) NOT NULL DEFAULT '0', 
    `title_seo` varchar(250) NOT NULL DEFAULT '', 
    `seo_last_name` varchar(255) NOT NULL DEFAULT '', 
    `seo_first_name` varchar(255) NOT NULL DEFAULT '', 
    PRIMARY KEY (`tid`), 
    KEY `topic_firstpost` (`topic_firstpost`), 
    KEY `forum_id` (`forum_id`,`pinned`,`approved`), 
    KEY `last_post` (`forum_id`,`pinned`,`last_post`), 
    KEY `starter_id` (`starter_id`,`forum_id`,`approved`), 
    KEY `last_post_sorting` (`last_post`,`forum_id`), 
    KEY `start_date` (`start_date`), 
    FULLTEXT KEY `title` (`title`) 
) ENGINE=MyISAM AUTO_INCREMENT=227233 DEFAULT CHARSET=latin1 
1 row in set (0.00 sec) 

表屬性是:

SHOW TABLE STATUS LIKE 'forum_members'\G 
*************************** 1. row *************************** 
      Name: forum_members 
     Engine: MyISAM 
     Version: 10 
    Row_format: Dynamic 
      Rows: 64866 
Avg_row_length: 257 
    Data_length: 16688164 
Max_data_length: 281474976710655 
    Index_length: 6540288 
     Data_free: 0 
Auto_increment: 101965 
    Create_time: 2009-12-02 05:45:59 
    Update_time: 2009-12-02 05:46:07 
    Check_time: 2009-12-02 05:49:23 
     Collation: latin1_swedish_ci 
     Checksum: NULL 
Create_options: 
     Comment: 
1 row in set (0.00 sec) 
------------------------------------------------------------------------------- 
SHOW TABLE STATUS LIKE 'forum_posts'\G 
*************************** 1. row *************************** 
      Name: forum_posts 
     Engine: MyISAM 
     Version: 10 
    Row_format: Dynamic 
      Rows: 581777 
Avg_row_length: 720 
    Data_length: 419170168 
Max_data_length: 281474976710655 
    Index_length: 46439424 
     Data_free: 0 
Auto_increment: 988489 
    Create_time: 2009-12-02 05:47:04 
    Update_time: 2009-12-02 05:48:13 
    Check_time: 2009-12-02 05:49:28 
     Collation: latin1_swedish_ci 
     Checksum: NULL 
Create_options: 
     Comment: 
1 row in set (0.00 sec) 
------------------------------------------------------------------------------- 
SHOW TABLE STATUS LIKE 'forum_topics'\G 
*************************** 1. row *************************** 
      Name: forum_topics 
     Engine: MyISAM 
     Version: 10 
    Row_format: Dynamic 
      Rows: 117458 
Avg_row_length: 144 
    Data_length: 17004836 
Max_data_length: 281474976710655 
    Index_length: 14105600 
     Data_free: 0 
Auto_increment: 227233 
    Create_time: 2009-12-02 05:48:38 
    Update_time: 2009-12-02 05:48:43 
    Check_time: 2009-12-02 05:49:28 
     Collation: latin1_swedish_ci 
     Checksum: NULL 
Create_options: 
     Comment: 
1 row in set (0.00 sec) 

其他配置細節:

SHOW VARIABLES LIKE '%buffer%'\G 
*************************** 1. row *************************** 
Variable_name: bulk_insert_buffer_size 
     Value: 8388608 
*************************** 2. row *************************** 
Variable_name: innodb_buffer_pool_size 
     Value: 8388608 
*************************** 3. row *************************** 
Variable_name: innodb_log_buffer_size 
     Value: 1048576 
*************************** 4. row *************************** 
Variable_name: join_buffer_size 
     Value: 131072 
*************************** 5. row *************************** 
Variable_name: key_buffer_size 
     Value: 8384512 
*************************** 6. row *************************** 
Variable_name: myisam_sort_buffer_size 
     Value: 8388608 
*************************** 7. row *************************** 
Variable_name: net_buffer_length 
     Value: 16384 
*************************** 8. row *************************** 
Variable_name: pbxt_log_buffer_size 
     Value: 256K 
*************************** 9. row *************************** 
Variable_name: pbxt_transaction_buffer_size 
     Value: 1MB 
*************************** 10. row *************************** 
Variable_name: preload_buffer_size 
     Value: 32768 
*************************** 11. row *************************** 
Variable_name: read_buffer_size 
     Value: 131072 
*************************** 12. row *************************** 
Variable_name: read_rnd_buffer_size 
     Value: 262144 
*************************** 13. row *************************** 
Variable_name: sort_buffer_size 
     Value: 2097144 
*************************** 14. row *************************** 
Variable_name: sql_buffer_result 
     Value: OFF 
14 rows in set (0.00 sec) 
+1

輸出的行數(大致)?解釋告訴我們它正在查看'forum_topics'表中似乎有太多行,但我不能確定,除非我知道預計有多少行... – 2009-12-02 10:39:13

+0

@Vegard Larsen:好問題! :)輸出大約4,006行。查詢在這裏花費2到5秒,具體取決於表碎片。 :| – 2009-12-03 22:07:54

+0

購買固態硬盤? ;) – Kurt 2009-12-05 08:43:50

回答

1

通過將某些WHERE子句條件移到JOIN中,您可能會獲得更高的性能,因爲這會在執行查詢時削減結果集,例如,

SELECT p.author_id   member_id, 
     m.members_display_name member_name, 
     COUNT(p.pid)   posts 
FROM forum_topics t 
    STRAIGHT_JOIN forum_posts p 
    ON   t.tid  = p.topic_id 
    AND   t.forum_id = 120 
    AND p.new_topic = 0 
    STRAIGHT_JOIN forum_members m 
    ON p.author_id = m.member_id 
WHERE p.author_id != 0  
GROUP BY p.author_id 
ORDER BY posts DESC 
LIMIT 1 

儘管優化器可能足夠聰明,可以爲您做到這一點。另外,儘管我沒有使用MySQL,但是我對STRAIGH_JOIN的理解是,它以明確的從左到右的順序連接這些表,因此如果表的大小順序從最小到最大以及反之亦然,它們可能會有所不同。

+0

超過3年後...(我從另一個已合併的帳戶中恢復了此問題)謝謝,謝謝,謝謝!這幫助了很多,也幫助我瞭解了更多關於JOIN的內容。 :) – 2013-02-15 01:42:26