2014-04-22 6 views
2

나는 3 개의 테이블을 가지고 있습니다. 임 그들을 여기수정 색인 사용, 임시 사용, 파일 사용

SELECT `t`.`title` AS `category_title`,`t`.`id` AS `category_id`, `st`.`title` AS 
`subcategory_title`, `st`.`id` AS `subcategory_id`, `st`.`parent_id` AS 
`subcategory_parent`, `n`.`title` AS `news_title`,`n`.`id` AS `news_id` FROM 
`t_categories` `t` LEFT JOIN t_categories AS `st` ON `st`.`parent_id`=t.`id` LEFT JOIN 
t_newsrelations AS `nr` ON `nr`.`category_id`=st.`id` LEFT JOIN t_news AS `n` ON 
`n`.`id`=nr.`news_id` WHERE `t`.`enabled` = 1 AND `n`.`enabled` = 1 AND `n`.`type`!=1 AND 
`n`.`type`!=5 ORDER BY `t`.`position`,`st`.`position`,`n`.`position` ASC 

에 참여 왼쪽하려고하는 테이블

CREATE TABLE IF NOT EXISTS `t_categories` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `parent_id` int(11) NOT NULL, 
    `title` tinytext NOT NULL, 
    `position` tinyint(4) unsigned NOT NULL DEFAULT '0', 
    `type` tinyint(1) unsigned NOT NULL, 
    `enabled` tinyint(1) unsigned NOT NULL DEFAULT '1', 
    UNIQUE KEY `id` (`id`), 
    KEY `type` (`type`), 
    KEY `parent_id` (`parent_id`), 
    KEY `enabled` (`enabled`), 
    KEY `id_parent_position_enabled` (`id`,`parent_id`,`position`,`enabled`), 
    KEY `position` (`position`), 
    KEY `parent_id_2` (`parent_id`,`enabled`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; 


CREATE TABLE IF NOT EXISTS `t_news` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `title` tinytext NOT NULL, 
    `m_title` tinytext NOT NULL, 
    `url` varchar(2000) NOT NULL, 
    `keywords` text NOT NULL, 
    `description` text NOT NULL, 
    `body` longtext NOT NULL, 
    `position` tinyint(4) unsigned NOT NULL DEFAULT '0', 
    `type` tinyint(1) unsigned NOT NULL, 
    `city_id` int(4) NOT NULL, 
    `quickmenu_enabled` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    `quickmenu` text NOT NULL, 
    `enabled` tinyint(1) unsigned NOT NULL DEFAULT '1', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `id` (`id`), 
    KEY `position` (`position`), 
    KEY `type` (`type`), 
    KEY `city_id` (`city_id`), 
    KEY `url` (`url`(333)), 
    KEY `quickmenu_enabled` (`quickmenu_enabled`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; 


CREATE TABLE IF NOT EXISTS `t_newsrelations` (
    `category_id` int(11) NOT NULL, 
    `news_id` int(11) unsigned NOT NULL, 
    KEY `category_id` (`category_id`), 
    KEY `news_id` (`news_id`), 
    KEY `category_id_2` (`category_id`,`news_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

의 구조 그리고 EXPLAIN SELECT 것은

explain-img t_newsrelations 중간 테이블 인 나에게 보여줍니다. 표 t_categories에는 parent_id 열로 연결된 범주 및 하위 범주가 포함되어 있습니다. t_news의 각 항목은 둘 이상의 하위 범주의 구성원이 될 수 있습니다. 왜 그들은 t_newsrelations를 통해 연결된 이유가 무엇입니까?

쿼리를 최적화하는 방법은 무엇입니까? 표시 이유 왜 인덱스 사용, 임시 사용, 파일 사용? 여러 테이블에서 열을 정렬하고 있기 때문에

+0

27 개의 레코드 만 있습니까? – Frazz

+0

이것은 현재 사용하고 있습니다. 사이트의 제작 모드를 활성화 한 상태입니다. – Undrooleek

+1

그러나 설명은 데이터베이스 통계에 달려 있다는 것을 알고 있습니까? 다른 쿼리로 채워진 데이터베이스가있는 동일한 쿼리는 다른 EXPLAIN을 생성 할 수 있습니다. 테이블이 작을 때 일부 엔진은 인덱스를 모두 무시하고 테이블을 순차적으로 읽습니다. 실제 또는 실제 데이터가 없다면 (IMHO) 데이터베이스를 실제로 최적화 할 수 없습니다. – Frazz

답변

3
ORDER BY `t`.`position`,`st`.`position`,`n`.`position` ASC 

당신은, 당신이 가지고있는 테이블 주어,이 쿼리에서 임시 테이블 및 filesort를 제거 할 수 있습니다. 정렬 최적화는 쿼리가 원하는 순서대로 행을 가져올 수 있도록 인덱스를 사용한다는 것을 의미합니다. 그러나 MySQL에는 여러 테이블에 걸쳐 인덱스를 생성 할 수있는 방법이 없습니다.

이 문제를 해결하는 유일한 방법은 세 개의 열이 모두 하나의 테이블에 있어야하고 세 개의 열에 대해 하나의 인덱스를 만들 때까지 비정규 화하는 것입니다. 그러나 비정규 화는 자체 단점이 있습니다.