2013-07-04 2 views
0
SELECT links.* 
FROM links 
INNER JOIN (
    SELECT keywords_links.link_id 
    FROM keywords_links 
    INNER JOIN keywords ON keywords_links.keyword_id = keywords.id 
    WHERE keywords.keyword 
    IN ("facebook", "google", "apple") 
    GROUP BY keywords_links.link_id 
) t 
ON links.id = t.link_id 

키워드와 일치하는 링크를 반환합니다. 나는 3 개의 테이블을 가지고있다 : links, keywords, 그리고 keywords_links. keywords_links은 링크와 키워드를 연결합니다.MySQL 쿼리가 느립니다.

어떻게이 쿼리를보다 효율적으로 만들 수 있습니까? 나는 MySQL에 익숙하지 않았기 때문에 기본 MySQL 명령을 사용하여이 쿼리를 작성해야했습니다. (에만 관련 정보가 표시)

테이블 :

링크 :

CREATE TABLE IF NOT EXISTS `links` (
    `id` int(11) NOT NULL auto_increment, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `url` (`url`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=337789 ; 

keywords_links :

CREATE TABLE IF NOT EXISTS `keywords_links` (
    `keyword_id` int(11) NOT NULL, 
    `link_id` int(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

키워드 :

CREATE TABLE IF NOT EXISTS `keywords` (
    `id` int(11) NOT NULL auto_increment, 
    `keyword` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `sort` (`id`,`keyword`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=60363 ; 
+0

왜 여기에 'GROUP BY'가 필요한가요? – zerkms

+0

1.'EXPLAIN'을 보여줍니다. 2. 모든 테이블에 대해'CREATE TABLE'을 보여줍니다. – zerkms

+0

'ON'과'WHERE' 절에 사용 된 모든 열에 인덱스가 있는지 확인하십시오. – Barmar

답변

0

자체가 괜찮 쿼리를 제거 DISTINCT을 추가했습니다. 성능 문제는 키워드를 일치시키기 위해 keywords_links 전체 테이블 스캔을 수행하고 일치하는 항목을 찾기 위해 전체 테이블 스캔을 키워드에서 수행해야하는 것일 수 있습니다.

는에 테이블 구조를 변경해보십시오 :

CREATE TABLE IF NOT EXISTS `keywords` (
    `id` int(11) NOT NULL auto_increment, 
    `keyword` varchar(100) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `sort` (`id`,`keyword`), 
    INDEX (keyword) 
) ; 

이 키워드 검색을 빠르게한다 (당신은 또한 create index을 사용할 수 있습니다).

다음, 그래서 당신이 링크를 빠르게 찾을 수 있습니다

CREATE TABLE IF NOT EXISTS `keywords_links` (
    `keyword_id` int(11) NOT NULL, 
    `link_id` int(11) NOT NULL, 
    unique (keyword_id, link_id) 
); 

인덱스를 통해 키워드에 일치하는 항목을 찾아 다음 쿼리를 가속화한다 인덱스를 통해 링크를 찾을 수의 조합.

+0

innodb가되면 바로'keyword' 테이블에서 고유 한'keyword' 인덱스로 충분합니다. 총 2 개의 인덱스, 즉 PK (id)와 UNIQUE KEY (키워드) – zerkms

+0

@zerkms 만 있습니다. . . 당신이 올바른지. 질문에서, 문장은'unique sort (id, keyword)'입니다. 이것은 매우 다릅니다. –

0
SELECT DISTINCT 
    l.* 
FROM 
links l 
INNER JOIN keyworks_links kl ON kl.link_id = l.id 
INNER JOIN keywords ON kl.keyword_id = k.id 
WHERE 
    k.keyword IN ("facebook", "google", "apple") 
; 

편집 중복

+0

무엇이 더 빨리 달릴 것입니까? –

+0

원래 형식으로 인라인 테이블 (from의 subselect)을 작성한 다음 해당 인라인 테이블을 links 테이블과 조인합니다.인라인 테이블은 join을위한 인덱스를 사용하지 않을 것이고, mysql은 인덱스를 사용할 것입니다. (필요하다면) – Aguardientico

+0

단지 부수적 인 질문입니다.이 질문의 질의는 중첩 된 쿼리에서 중복 된'link_id'를 보장하지 않습니다. 't – zerkms

관련 문제