2013-07-25 3 views
3
mysql> explain 
    select c.userEmail,f.customerId 
    from comments c 
     inner join flows f 
     on (f.id = c.typeId) 
     inner join users u 
     on (u.email = c.userEmail) 
    where c.addTime >= 1372617000 
     and c.addTime <= 1374776940 
     and c.type = 'flow' 
     and c.automated = 0; 
+----+-------------+-------+--------+----------------------------------------+------------+---------+---------------------+--------+-------------+ 
| id | select_type | table | type | possible_keys       | key  | key_len | ref     | rows | Extra  | 
+----+-------------+-------+--------+----------------------------------------+------------+---------+---------------------+--------+-------------+ 
| 1 | SIMPLE  | f  | index | PRIMARY        | customerId | 4  | NULL    | 144443 | Using index | 
| 1 | SIMPLE  | c  | ref | userEmail_idx,addTime,automated,typeId | typeId  | 198  | f.id,const |  1 | Using where | 
| 1 | SIMPLE  | u  | eq_ref | email         | email  | 386  | c.userEmail |  1 | Using index | 
+----+-------------+-------+--------+----------------------------------------+------------+---------+---------------------+--------+-------------+ 

어떻게 위 쿼리를 더 빠르게 만들 수 있습니까? 느린 쿼리 로그에 끊임없이 나타납니다.
인덱스 현재 :MySQL 쿼리가 느림 - 모든 인덱스가있는 경우에도

  1. ID는 플로우 테이블의 기본 키 자동 증가이다.
  2. 고객 ID 흐름 표.
  3. userEmail 덧글 표.
  4. 의견 표에 복합 색인 (유형 ID, 유형).
  5. 사용자의 이메일 테이블 (고유)
  6. 자동으로 댓글 테이블.
  7. 덧글 시간의 덧셈 시간. 행

번호 :
1. 흐름 - 150K
2 댓글 - 50 만 (그 중 절반은 = 1 자동화하고 다른 사람이 공을 자동화 = 한) (도 유형의 값이 '흐름'모두를위한 것입니다 (500)를 제외하고 행)
3. 사용자 - 50

테이블 스키마 :

users | CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `email` varchar(128) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `email` (`email`) 
) ENGINE=InnoDB AUTO_INCREMENT=56 DEFAULT CHARSET=utf8 

comments | CREATE TABLE `comments` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `userEmail` varchar(128) DEFAULT NULL, 
    `content` mediumtext NOT NULL, 
    `addTime` int(11) NOT NULL, 
    `typeId` int(11) NOT NULL, 
    `automated` tinyint(4) NOT NULL, 
    `type` varchar(64) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `userEmail_idx` (`userEmail`), 
    KEY `addTime` (`addTime`), 
    KEY `automated` (`automated`), 
    KEY `typeId` (`typeId`,`type`) 
) ENGINE=InnoDB AUTO_INCREMENT=572410 DEFAULT CHARSET=utf8 | 


flows | CREATE TABLE `flows` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `type` varchar(32) NOT NULL, 
    `status` varchar(128) NOT NULL, 
    `customerId` int(11) NOT NULL, 
    `createTime` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `flowType_idx` (`type`), 
    KEY `customerId` (`customerId`), 
    KEY `status` (`status`), 
    KEY `createTime` (`createTime`), 
) ENGINE=InnoDB AUTO_INCREMENT=134127 DEFAULT CHARSET=utf8 | 
+6

'(automated, type, addTime) '에 색인을 추가해보십시오. –

+0

언급을 잊어 버렸습니다. 이미 addTime에 대한 색인이 있습니다. – dharm0us

+0

그냥 코멘트에 테이블을 최적화, 지금은 훨씬 적은 수의 출력을 보여줍니다 설명합니다. 또한 응용 프로그램의 컨텍스트에서 쿼리의 속도가 빨라지는지 확인할 것입니다. – dharm0us

답변

1

당신은 효율적으로 조인을 수행하는 데 필요한 인덱스를 가지고있다. 그러나 MySQL은 덜 효율적인 방식으로 테이블에 합류하는 것처럼 보입니다. EXPLAIN 출력은 flows 테이블의 전체 인덱스 스캔을 수행 중이며 comments 테이블에 합류하고 있음을 보여줍니다.

가입하기 전에 comments 테이블을 먼저 읽는 것이 더 효율적일 수 있습니다. 즉, 사용자가 제공 한 술어 (사용자가 의도 한 것)에 의해 주석 세트가 제한되도록 조회에서 지정한 순서대로 수행하십시오.

OPTIMISE TABLE 또는 ANALYZE TABLE을 실행하면 쿼리 최적화 프로그램이 결정을 향상시킬 수 있습니다. 특히 광범위한 변경 사항이있는 테이블

쿼리 최적화 프로그램이 계속 잘못 처리하면 문을 SELECT STRAIGHT_JOIN으로 시작하거나 INNER JOINSTRAIGHT_JOIN으로 변경하여 쿼리에서 지정한 순서대로 테이블을 읽도록 할 수 있습니다.

+0

straight_join을 지적 해 주셔서 감사합니다. 어딘가에 이상적인 해결책은 아니지만 다른 쿼리를 최적화하는 데 도움이되었습니다. – dharm0us