2010-12-16 3 views
2
SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY SourceId, ExternalProductId 
HAVING cnt > 1 

(ExternalProductId, SourceId, AnotherField)에 대한 색인이 있습니다. Explain은 인덱스가 사용되었음을 보여줍니다. 이것은의 "추가"열에 인쇄 설명 :다음 쿼리가 테이블 데이터를 복사하는 이유는 무엇입니까?

Using where; Using index; Using temporary; Using filesort 

나는 쇼 PROCESSLIST를 통해 내가 볼 쿼리 실행

Copying to tmp table on disk 

내가 지수 장소에서 작업이 쿼리를 조정할 수 있습니까? 또한이 테이블에서 동시에 작업하는 다른 프로세스로 인해 결과가 약간 부정확 할 수도 있습니다. 격리 수준을 변경하여 쿼리 성능을 향상시킬 수 있습니까? 시도

+2

나는 오해가 있다고 생각합니다. 임시 테이블은 작업을 수행하기 위해 테이블의 모든 데이터를 복사한다는 것을 의미하지 않습니다. 단지 중간 결과를 임시 테이블에 복사하여 나중에 처리 할 수 ​​있음을 의미합니다. 임시 테이블에는 ExternalProductID가 null이 아니고 cnt 열이있는 모든 레코드가 포함되어있어 'HAVING'절을 평가할 수 있습니다. 둘째, 트랜잭션 격리는 임시 테이블과 아무 관련이 없습니다. – bot403

+0

@ bot403 - 방금 DBA와 이야기를 나누었습니다. 그리고 그는 당신과 동의합니다. 나는 당신의 의견이 실제로이 질문에 대한 지금까지의 최선의 대답이라고 믿습니다. – ripper234

+0

예, 대답은 제 1 번과 ajreal의 색인 제안이라고 생각합니다. – bot403

답변

3

GROUP BY의 열을 복합 인덱스의 처음 두 필드의 순서에 맞게 반대로하면 복합 인덱스가 훨씬 효과적으로 사용됩니다.

SELECT COUNT(*) AS cnt 
FROM products 
WHERE ExternalProductId IS NOT NULL 
GROUP BY ExternalProductId, SourceId 
HAVING cnt > 1 

귀하의 쿼리 실행 일반은 'Using where; Using index'로 전환해야하며, 다른 GROUP BY에 의한 임시 테이블 및 filesort 모두 제거.

같은 결과를 얻지 만 약간 다른 순서로 표시됩니다.

+0

좋아요, 설명은 지금 임시 테이블을 실제로 보여주지 않습니다. 차이점이 있는지 확인하기 위해 쿼리 런타임을 측정 할 것입니다. – ripper234

0

몇 가지 :

  1. MySQL을 자동으로 정렬 그룹과. 정렬 순서에 신경 쓰지 않는다면 'ORDER BY NULL'절을 추가하십시오. 그러면 filesort와 temp 테이블을 꺼내게됩니다.

  2. 수 (*)를 제거하고 와일드 카드 대신 색인의 열 이름을 사용하십시오.

또한. 귀하의 색인은 무엇입니까? 전체 테이블 작성 명세서를 보여줄 수 있습니까?

+0

ORDER BY NULL은 여전히 ​​임시 테이블을 사용합니다 - 허용되는 대답을 참조하십시오. – ripper234

관련 문제