대안

2011-10-21 4 views
0

주어진 다음의 표를 하위 쿼리 :대안

CREATE TABLE IF NOT EXISTS `rank` ( 
`rank_id` bigint(20) NOT NULL AUTO_INCREMENT, 
`rank` int(10) NOT NULL DEFAULT '0', 
`subject_id` int(10) NOT NULL DEFAULT '0', 
`title_id` int(10) NOT NULL DEFAULT '0', 
`source_id` int(10) NOT NULL DEFAULT '0' 
PRIMARY KEY (`rank_id`) 
) ENGINE=MyISAM; 

INSERT INTO `rank` (`rank_id`, `rank`, `subject_id`, `title_id`, `source_id`) VALUES 
(23, 0, 2, 1, 1), 
(22, 0, 1, 1, 1), 
(15, 0, 2, 2, 2), 
(14, 0, 2, 2, 1), 
(20, 0, 1, 3, 2), 
(18, 0, 1, 4, 2), 
(19, 0, 1, 5, 2), 
(21, 0, 1, 3, 1), 
(24, 0, 1, 6, 2); 

CREATE TABLE IF NOT EXISTS `title` ( 
`title_id` bigint(20) NOT NULL AUTO_INCREMENT, 
`title` varchar(255) DEFAULT NULL, 
`description` text, 
`pre` varchar(255) DEFAULT NULL, 
`last_modified_by` varchar(50) DEFAULT NULL, 
`last_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`title_id`) 
) ENGINE=MyISAM; 

INSERT INTO `title` (`title_id`, `title`, `last_modified`) VALUES 
(1, 'new item', ' ', '2011-10-20 19:10:48'), 
(2, 'another test', '2011-10-20 19:10:48'), 
(3, 'and yet another', '2011-10-20 19:10:48'), 
(4, 'one more', ' ', '2011-10-20 19:10:48'), 
(5, 'adding more', ' ', '2011-10-20 19:10:48'), 
(6, 'yes, another', ' ', '2011-10-20 19:10:48'), 
(7, 'well, let''s see', ' ', '2011-10-20 19:10:48'); 

내 필요가 순위 테이블에서 주어진 주제에 연결되어 있지 않은 모든 제목을 선택하는 쿼리입니다.

나는 서브 쿼리를 통해이 작업이 :

SELECT title_id, title FROM title 
WHERE title_id NOT IN (SELECT title_id FROM rank WHERE subject_id=2) 

이 원하는 목록을 반환합니다 : 큰 데이터 세트가 조회 될 때

 
+----------+-----------------+ 
| title_id | title   | 
+----------+-----------------+ 
| 3  | and yet another | 
| 4  | one more  | 
| 5  | adding more  | 
| 6  | yes, another | 
| 7  | well, let's see | 
+----------+-----------------+ 

은 그러나, 조금 천천히 가져옵니다.

제 질문은 하위 쿼리를 사용하지 않고이 결과를 반환 할 방법이 있고이 대안이 더 빠른 경우 제 질문입니다.

미리 감사드립니다.

답변

3

빠른 하위 쿼리가 진행 중이지만 일반적으로 MySQL은 조인 속도가 빠릅니다.

SELECT t.* 
FROM title AS t 
LEFT JOIN rank AS r ON (t.title_id = r.title_id AND r.subject_id = 2) 
WHERE r.title_id IS NULL 

평소와 같이, 당신은 외래 키 (rank.title_id) 아마 쿼리 키 (rank.subject_id)에에 인덱스를 설정해야합니다.

자세한 내용은 [LEFT JOIN][1]의 MySQL 설명서를 읽어야합니다. ON과 함께 유용한 트릭을 사용하면 WHERE과 달라집니다.

+0

감사합니다. 결과가 완벽하게 복제 된 것 같습니다. – AndrewStevens

+0

해당 열을 인덱싱하는 데 성능이 크게 좌우되며 서브 쿼리 대 조인의 영향을받지 않을 수도 있음을 알고 있습니다. 그러나 조인과 함께 하위 쿼리를 복제하는 방법이 있어야하며 학습을 위해이를 파악하려고했습니다. 다시 한번 감사드립니다. – AndrewStevens

+0

업데이트 : 하위 쿼리 사용과 조인 사용 간의 속도 차이는 무시할 수있었습니다. 외래 키에 대한 인덱스를 설정하는 것은 쿼리를 실제로 만들었지 만. – AndrewStevens

1

MySQL EXPLAIN 명령은 쿼리가 도움이 필요한 곳을 알려줍니다. 예 : EXPLAIN select title_id, title FROM title WHERE title_id NOT IN (select title_id from rank where subject_id=2)

내 생각 엔 rank.subject_id에 색인이 없으므로 순위가 많은 행 (순위가 많은 경우)이 테이블 스캔을 유발한다는 것입니다.

1

subject_id 및 title_id에 두 개의 인덱스를 만들고 같은 값으로 시도하십시오.