2013-12-24 3 views
2

다음 두 쿼리에 대해 mysql의 EXPLAIN 출력을 이해하지 못합니다. 제 질의 MySQL은GROUP BY를 추가하면 어떻게이 쿼리를보다 효율적으로 만들 수 있습니까?

이 1,238,264 제 레코드를 선택한다 : 더

explain select 
    count(distinct utc.id) 
from 
    user_to_company utc 
inner join 
    users u 
     on utc.user_id=u.id 
where 
    u.is_removed=false 
group by 
    utc.user_id 
order by 
    utc.user_id asc limit 20; 

+----+-------------+--------+--------+----------------------------+--------------------+---------+-------------------------+------+-------------+ 
| id | select_type | table | type | possible_keys    | key    | key_len | ref      | rows | Extra  | 
+----+-------------+--------+--------+----------------------------+--------------------+---------+-------------------------+------+-------------+ 
| 1 | SIMPLE  | utc | index | user_id,FKF513E0271C2D1677 | FKF513E0271C2D1677 | 8  | NULL     | 20 | Using index | 
| 1 | SIMPLE  | u | eq_ref | PRIMARY     | PRIMARY    | 8  | utc.user_id    | 1 | Using where | 
+----+-------------+--------+--------+----------------------------+--------------------+---------+-------------------------+------+-------------+ 

: 제 쿼리

explain select 
    count(distinct utc.id) 
from 
    user_to_company utc 
inner join 
    users u 
     on utc.user_id=u.id 
where 
    u.is_removed=false 
order by 
    utc.user_id asc limit 20; 

+----+-------------+--------+------+----------------------------+---------+---------+---------------------------------+---------+-------------+ 
| id | select_type | table | type | possible_keys    | key  | key_len | ref        | rows | Extra  | 
+----+-------------+--------+------+----------------------------+---------+---------+---------------------------------+---------+-------------+ 
| 1 | SIMPLE  | u  | ALL | PRIMARY     | NULL | NULL | NULL       | 1238264 | Using where | 
| 1 | SIMPLE  | utc | ref | user_id,FKF513E0271C2D1677 | user_id | 8  | u.id       |  1 | Using index 

하는 GROUP BY은 20 레코드를 선택 MySQL이 만드는 첨가 info에는 사용자 테이블에 1333194 개의 레코드가 있고 user_to_company 테이블에 1327768 개의 레코드가 있습니다.

GROUP BY을 추가하면 mysql이 첫 번째 패스에서 20 레코드 만 선택하는 방법은 무엇입니까?

+0

*해야 할 첫 번째 검색어 *는 무엇입니까? 'where' 조건을 만족하는'utc.id'의 총 고유 카운트 인 하나의 행만 반환합니다. –

답변

3

utc.id의 모든 값을 찾으려면 첫 번째 쿼리에서 모든 데이터를 읽어야합니다. 전체 테이블에 대한 요약 인 하나의 행만 반환합니다. 따라서 모든 데이터를 생성해야합니다.

두 번째 쿼리는 각각 utc.user_id에 대해 별도의 합계를 생성합니다. limit 절이 있고 utc.user_id에 색인이 있습니다. MySQL은 utc.user_id의 처음 20 개 값을 얻기 위해 인덱스로 갈 수 있다는 것을 인식 할만큼 충분히 똑똑합니다. 그것은 카운트를 생성하기 위해 이들을 사용합니다.

MySQL이 똑똑하기 때문에 놀랍습니다. (로직은 꽤 잘 문서화되어 있지만 here). 그러나 두 번째 쿼리가 첫 번째 쿼리가 될 수없는 곳에서이 방법으로 최적화 될 수 있다는 것은 완벽한 의미입니다.

+0

MYSQL은 인덱스를 사용하여 두 번째 쿼리의 처음 20 개 값을 얻는 것을 처음에는 알지 못합니다. – Glide

+0

@ 글라이드. . . 첫 번째 쿼리는'select' 절의 집계 함수 때문에 * 1 * 행만 반환합니다. 이 행에 대한 계산에는'count (distinct) '이기 때문에 테이블의 모든 데이터가 필요합니다. –

관련 문제