2013-07-09 28 views
-3
使用的filesort

我試圖優化查詢,避免使用文件排序:優化MySQL查詢,避免排序依據

/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */; 
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */; 
/*!40101 SET @[email protected]@COLLATION_CONNECTION */; 
/*!40101 SET NAMES utf8 */; 
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */; 


DROP TABLE IF EXISTS `comment`; 

CREATE TABLE `comment` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `thread_id` int(11) NOT NULL, 
    `parent_id` int(11) DEFAULT NULL, 
    `user_id` int(11) NOT NULL, 
    `body` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `created_at` datetime NOT NULL, 
    `state` int(11) NOT NULL, 
    `abuse_count` int(11) DEFAULT NULL, 
    `prediction_1` int(11) DEFAULT NULL, 
    `prediction_2` int(11) DEFAULT NULL, 
    `prediction_3` int(11) DEFAULT NULL, 
    `prediction_4` int(11) DEFAULT NULL, 
    `prediction_5` int(11) DEFAULT NULL, 
    `prediction_6` int(11) DEFAULT NULL, 
    `prediction_7` int(11) DEFAULT NULL, 
    `prediction_8` int(11) DEFAULT NULL, 
    `prono_concours` tinyint(1) DEFAULT NULL, 
    `prono_points` double DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_9474526CE2904019` (`thread_id`), 
    KEY `IDX_9474526C727ACA70` (`parent_id`), 
    KEY `IDX_9474526CA76ED395` (`user_id`), 
    KEY `IDX_PRONO` (`prono_concours`), 
    KEY `IDX_CREATED_AT_STATE` (`created_at`,`state`), 
    CONSTRAINT `FK_9474526C727ACA70` FOREIGN KEY (`parent_id`) REFERENCES `comment` (`id`), 
    CONSTRAINT `FK_9474526CA76ED395` FOREIGN KEY (`user_id`) REFERENCES `customer_user` (`id`), 
    CONSTRAINT `FK_9474526CE2904019` FOREIGN KEY (`thread_id`) REFERENCES `comment_thread` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

DROP TABLE IF EXISTS `comment_thread`; 

CREATE TABLE `comment_thread` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `is_commentable` tinyint(1) NOT NULL, 
    `num_comments` int(11) NOT NULL, 
    `last_comment_at` datetime DEFAULT NULL, 
    `site_id` int(11) NOT NULL, 
    `content_id` int(11) NOT NULL, 
    `content_type` int(11) NOT NULL, 
    `race_date` datetime DEFAULT NULL, 
    `num_race` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `UNIQ_COMMENT_SITEID` (`site_id`,`content_id`,`content_type`), 
    KEY `IDX_SITEID` (`site_id`), 
    KEY `IDX_CONTENT` (`content_id`,`content_type`), 
    KEY `IDX_COMMENTABLE` (`is_commentable`), 
    KEY `IDX_LAST_COMMENT` (`last_comment_at`), 
    KEY `IDX_CONTENT_TYPE` (`content_type`), 
    KEY `IDX_RACEDATE` (`race_date`), 
    KEY `IDX_NUMRACE` (`num_race`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 


DROP TABLE IF EXISTS `customer_user`; 

CREATE TABLE `customer_user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `username_canonical` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `email_canonical` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `enabled` tinyint(1) NOT NULL, 
    `salt` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `last_login` datetime DEFAULT NULL, 
    `locked` tinyint(1) NOT NULL, 
    `expired` tinyint(1) NOT NULL, 
    `expires_at` datetime DEFAULT NULL, 
    `confirmation_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `password_requested_at` datetime DEFAULT NULL, 
    `roles` longtext COLLATE utf8_unicode_ci NOT NULL COMMENT '(DC2Type:array)', 
    `credentials_expired` tinyint(1) NOT NULL, 
    `credentials_expire_at` datetime DEFAULT NULL, 
    `date_subscription` datetime NOT NULL, 
    `last_login_ip` bigint(20) NOT NULL, 
    `ref_client_le_turf` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `UNIQ_D902723E92FC23A8` (`username_canonical`), 
    UNIQUE KEY `UNIQ_D902723EA0D96FBF` (`email_canonical`), 
    KEY `IDX_LAST_LOGIN_IP` (`last_login_ip`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 




/*!40111 SET [email protected]_SQL_NOTES */; 
/*!40101 SET [email protected]_SQL_MODE */; 
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */; 
/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */; 
/*!40101 SET [email protected]_CHARACTER_SET_RESULTS */; 
/*!40101 SET [email protected]_COLLATION_CONNECTION */; 

這裏是我想優化(不使用使用的filesort,這似乎查詢是由於排序):

EXPLAIN 
SELECT c0_.id AS id0, c0_.body AS body1, c0_.created_at AS created_at2, c0_.state AS state3, c0_.abuse_count AS abuse_count4, c0_.prediction_1 AS prediction_15, c0_.prediction_2 AS prediction_26, c0_.prediction_3 AS prediction_37, c0_.prediction_4 AS prediction_48, c0_.prediction_5 AS prediction_59, c0_.prediction_6 AS prediction_610, c0_.prediction_7 AS prediction_711, c0_.prediction_8 AS prediction_812, c0_.prono_concours AS prono_concours13, c0_.prono_points AS prono_points14, c1_.id AS id15, c1_.is_commentable AS is_commentable16, c1_.num_comments AS num_comments17, c1_.last_comment_at AS last_comment_at18, c1_.site_id AS site_id19, c1_.content_id AS content_id20, c1_.content_type AS content_type21, c1_.race_date AS race_date22, c1_.num_race AS num_race23, c2_.username AS username24, c2_.username_canonical AS username_canonical25, c2_.email AS email26, c2_.email_canonical AS email_canonical27, c2_.enabled AS enabled28, c2_.salt AS salt29, c2_.password AS password30, c2_.last_login AS last_login31, c2_.locked AS locked32, c2_.expired AS expired33, c2_.expires_at AS expires_at34, c2_.confirmation_token AS confirmation_token35, c2_.password_requested_at AS password_requested_at36, c2_.roles AS roles37, c2_.credentials_expired AS credentials_expired38, c2_.credentials_expire_at AS credentials_expire_at39, c2_.id AS id40, c2_.date_subscription AS date_subscription41, c2_.last_login_ip AS last_login_ip42, c2_.ref_client_le_turf AS ref_client_le_turf43, c0_.thread_id AS thread_id44, c0_.parent_id AS parent_id45, c0_.user_id AS user_id46 
FROM comment c0_ 
LEFT JOIN comment_thread c1_ ON c0_.thread_id = c1_.id 
LEFT JOIN customer_user c2_ ON c0_.user_id = c2_.id 
WHERE c1_.site_id = 2 AND c0_.state = 1 
ORDER BY c0_.created_at DESC LIMIT 10; 

如果你有一個解決方案...我會很好!

非常感謝!

----------------- UPDATE: -----------------

後您的答案,我重新運行一個測試,我仍然有「使用Filesort」。

如果你有一個想法,告訴我讓它消失。我無法刪除ORDER BY語句。

mysql> EXPLAIN 
    -> SELECT c0_.id AS id0, c0_.body AS body1, c0_.created_at AS created_at2, c0_.state AS state3, c0_.abuse_count AS abuse_count4, c0_.prediction_1 AS prediction_15, c0_.prediction_2 AS prediction_26, c0_.prediction_3 AS prediction_37, c0_.prediction_4 AS prediction_48, c0_.prediction_5 AS prediction_59, c0_.prediction_6 AS prediction_610, c0_.prediction_7 AS prediction_711, c0_.prediction_8 AS prediction_812, c0_.prono_concours AS prono_concours13, c0_.prono_points AS prono_points14, c1_.id AS id15, c1_.is_commentable AS is_commentable16, c1_.num_comments AS num_comments17, c1_.last_comment_at AS last_comment_at18, c1_.site_id AS site_id19, c1_.content_id AS content_id20, c1_.content_type AS content_type21, c1_.race_date AS race_date22, c1_.num_race AS num_race23, c2_.username AS username24, c2_.username_canonical AS username_canonical25, c2_.email AS email26, c2_.email_canonical AS email_canonical27, c2_.enabled AS enabled28, c2_.salt AS salt29, c2_.password AS password30, c2_.last_login AS last_login31, c2_.locked AS locked32, c2_.expired AS expired33, c2_.expires_at AS expires_at34, c2_.confirmation_token AS confirmation_token35, c2_.password_requested_at AS password_requested_at36, c2_.roles AS roles37, c2_.credentials_expired AS credentials_expired38, c2_.credentials_expire_at AS credentials_expire_at39, c2_.id AS id40, c2_.date_subscription AS date_subscription41, c2_.last_login_ip AS last_login_ip42, c2_.ref_client_le_turf AS ref_client_le_turf43, c0_.thread_id AS thread_id44, c0_.parent_id AS parent_id45, c0_.user_id AS user_id46 
    -> FROM comment c0_ 
    -> INNER JOIN comment_thread c1_ ON c0_.thread_id = c1_.id 
    -> INNER JOIN customer_user c2_ ON c0_.user_id = c2_.id 
    -> WHERE c1_.site_id = 2 AND c0_.state = 1 
    -> ORDER BY c0_.created_at DESC LIMIT 10; 
+----+-------------+-------+--------+---------------------------------------------------------------------------+----------------------+---------+--------------------------+------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys                | key     | key_len | ref      | rows | Extra          | 
+----+-------------+-------+--------+---------------------------------------------------------------------------+----------------------+---------+--------------------------+------+----------------------------------------------+ 
| 1 | SIMPLE  | c1_ | range | PRIMARY,UNIQ_COMMENT_SITEID,IDX_SITEID,IDX_ID_SITEID      | UNIQ_COMMENT_SITEID | 4  | NULL      | 234 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | c0_ | ref | IDX_9474526CE2904019,IDX_9474526CA76ED395,IDX_STATE,IDX_STATE_DATE_CREATE | IDX_9474526CE2904019 | 4  | turfeditions.c1_.id  | 16 | Using where         | 
| 1 | SIMPLE  | c2_ | eq_ref | PRIMARY                 | PRIMARY    | 4  | turfeditions.c0_.user_id | 1 |            | 
+----+-------------+-------+--------+---------------------------------------------------------------------------+----------------------+---------+--------------------------+------+----------------------------------------------+ 
3 rows in set (0.00 sec) 
+0

請在看到這篇文章,然後再決定是否需要讓Filesort離開。 http://www.mysqlperformanceblog.com/2009/03/05/what-does-using-filesort-mean-in-mysql/ –

回答

0

首先,您需要澄清一些事情。由於您擁有「and c1_.site_id = 2」,因此您的LEFT-JOIN到comment_thread表被處理爲INNER-JOIN。如果你真的想它作爲一個左聯接,移動和子句SITE_ID到左JOIN ...如

FROM 
     comment c0_ 
     LEFT JOIN comment_thread c1_ 
      ON c0_.thread_id = c1_.id 
      AND c1_.site_id = 2 
     LEFT JOIN customer_user c2_ 
      ON c0_.user_id = c2_.id 
    WHERE 
     c0_.state = 1 
    ORDER BY 
     c0_.created_at DESC 
    LIMIT 10; 

現在,這麼說,我會在對comment_thread表的索引( ID,Site_ID)。在評論表上,我會有一個關於(state,created_at)的索引。

通過左連接,它將拉取state = 1的所有註釋REGALDLESS在comment_thread或customer_user中有一個匹配條目(即使每個帖子都希望有一個用戶發佈它並且左連接應該是真的只是一個內部聯接)