2011-01-10 3 views
0

감사합니다.쿼리에서 GROUP BY를 사용할 때 MySQL 테이블 인덱싱에 대한 도움말

저자

id  INT 
nickname VARCHAR(50) 
status ENUM('active', 'blocked') 
about  TEXT 

author_id INT 
title  VARCHAR(150) 

나는 각 저자를 얻기 위해,이 테이블에 대해 쿼리를 실행 해요 :

두 InnoDB 테이블이 있습니다 그가 가지고있는 책의 수 :

SELECT a. * , COUNT(b.id) AS book_count 
FROM authors AS a, books AS b 
WHERE a.status != 'blocked' 
AND b.author_id = a.id 
GROUP BY a.id 
ORDER BY a.nickname 

이 쿼리는 매우 느립니다 (실행하는 데 약 6 초 걸림). 난 books.author_id에 대한 색인을 가지고 완벽하게 작동하지만,이 쿼리는 그것을 사용할 수 있도록 authors 테이블에 색인을 만드는 방법을 모르겠다. 여기

는 모습을 EXPLAIN 방법 전류 :

id select_type table type possible_keys    key   key_len ref  rows Extra 
1 SIMPLE  a  ALL  PRIMARY,id_status_nickname NULL   NULL  NULL 3305 Using where; Using temporary; Using filesort 
1 SIMPLE  b  ref  key_author_id    key_author_id 5   a.id 2  Using where; Using index 

내가 MySQL manual on optimizing queries with group by을 검토 한 결과,하지만 난 내 쿼리를 적용 할 수있는 방법을 알아낼 수 없었다.

나는 이것에 대한 도움과 힌트를 주셔서 감사합니다. MySQL이 사용할 수 있도록 인덱스 구조 여야합니다.

편집은

나는 시도했다 :

(id, status, nickname) 
(status, nickname) 

이 같은 상황의 결과.

+0

색인 생성을위한 기본 규칙은 조인 및/또는 where 절에서 사용하는 모든 필드를 색인화해야한다는 것입니다. 귀하의 질의에 대해, 그것은 a.id, b.author_id 및 a를 의미합니다.상태를 모두 색인화해야합니다. –

답변

3

id_status_nickname이 복합 색인 (id, status, nickname)이라고 가정합니다. 쿼리에서 a.status! = blocked라고 말하여 행을 필터링합니다. 다음과 같은 문제가 있습니다 :

  1. 이 경우 사용할 수있는 색인이 없습니다. 상태가 해당 색인의 접두어가 아니기 때문에 (id, status, nickname) 사용할 수 없습니다.
  2. 상태에 대한 색인이 있다고 가정하면! =을 사용할 때 사용할 수 없습니다. status = 'active'로 변경해야합니다.
  3. 또한 상태는 단지 두 개의 값만있는 enum 필드이므로 카디널리티가 낮습니다. 따라서 mysql은 인덱스를 전혀 사용하지 않을 수 있습니다.

시도해 볼 수 있습니다. (status, id, nickname)으로 색인을 생성하고 status = 'active'를 사용할 수 있습니다. 내 생각 엔 당신이 '='을 사용하고 상태가 색인의 접두사이므로이 색인을 선택하고 그룹별로 사용 ​​한 다음 by.order를 사용하여 색인을 생성합니다. 이것이 도움이됩니다.

업데이트 : WHERE 절에 ORDER BY에 사용 된 필드가없는 경우 파일 포트를 피할 수없는 것처럼 보입니다.

0

나는 (상태, 닉네임)에 대한 색인을 시도 할 것이다. "filesort 사용"의 필요성을 제거해야합니다.

관련 문제