2009-12-02 5 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' 테이블에 너무 많은 행이있는 것을보고 있지만, 얼마나 많은 행이 예상되는지 알지 못하면 확신 할 수 없습니다. –

+0

@Vegard Larsen : 좋은 질문입니다! :) 출력은 약 4,006 행입니다. 쿼리는 테이블 조각화에 따라 여기에서 2 ~ 5 초가 걸렸습니다. : | –

+0

솔리드 스테이트 드라이브를 구입 하시겠습니까? ;) – Kurt

답변

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에 대해 좀 더 배웠습니다. :) –

관련 문제