2014-04-04 3 views
0

내 SQL 내가 쿼리의 모든 필드에 인덱스가이 MySQL 쿼리를 최적화 할 수 있습니까?

SELECT authors.*, COUNT(*) FROM authors 
    INNER JOIN resources_authors ON authors.author_id=resources_authors.author_id 
WHERE 
    resource_id IN 
     (SELECT resource_id FROM resources_authors WHERE author_id = '1313') 
    AND authors.author_id != '1313' 
GROUP BY authors.author_id` 

,하지만 난 여전히 Using temporary; Using Filesort를 얻을.

id select_type   table    type   possible_keys       key  key_len ref    rows Extra 
1 PRIMARY    authors   ALL    PRIMARY        NULL  NULL NULL    16025 Using where; Using temporary; Using filesort 
1 PRIMARY    resources_authors ref    author_id        author_id  4 authors.author_id  3 Using where 
2 DEPENDENT SUBQUERY resources_authors unique_subquery resource_id,author_id,resource_id_2 resource_id 156 func,const    1 Using index; Using where 

이 쿼리의 속도를 높이려면 쿼리 또는 테이블 구조를 어떻게 향상시킬 수 있습니까? http://sqlfiddle.com/#!2/96d57/2/0

+0

'author_id! = 1313'은 색인을 효과적으로 사용할 수 있다고 생각하지 않습니다. – Barmar

+0

@MKhalidJunaid - 결코 결과를 반환하지 않으므로 작동하지 않습니다. –

+0

왜 이드는 1313이어야하고 1313이 아니라고 말할까요? ... 기본적으로 당신은 자존심이있는 자원이 1313이고 저자가 1313이 아닌 곳을 찾아 내고 있습니다. –

답변

1

가 나는 "PreQuery"을 수행하여 그것을 다른 방식으로 접근하는 것입니다 : 당신이 실험을하려는 경우

는 여기에 SQL 바이올린있다. 다른 작성자에게 공통된 자원 수를 가지고 있지만 최종 저자 목록에 원본 저자를 포함시키지 않은 모든 저자의 목록을 가져옵니다. 해당 저자가 결정되면 이름/연락처 정보와 공통 자원의 총 수를 얻지 만 공통적 인 특정 자원은 얻지 못합니다. 이것은 약간 다른 쿼리 일 것입니다.

이제 쿼리. 쿼리를 최적화하는 데 도움이되도록 에 두 개의 인덱스가 있습니다 (author_id) 다른 조합 (resource_id, author_id) 에 이미 있습니다.

이제 내부 쿼리에 대해 설명합니다. 먼저 그 부분을 수행하면 실행 계획이 인덱스를 활용할 수 있습니다. 여기서 의도는 리소스 작성자로 시작하지만이 결과 집합을 매우 짧게 유지할 특정 작성자 (where 절) 만 고려합니다. 그것은 즉시 리소스 작성자 테이블에 다시 가입되지만 동일한 리소스 및 작성자 만이 다른 작성자 만 제공하는 기본 where (where 절에서)가 아닙니다. COUNT ()를 추가하여 각 제안에 대해 저작자 당 하나의 항목을 반환하는 작성자별로 그룹화 된 공통 리소스가 몇 개인 지 식별합니다. 마지막으로 "PreQuery"결과 세트 (위에서 이미 사전 검증 된 모든 레코드)를 가져 와서 작성자에게 참여하십시오. 세부 사항 및 계산 () 완료.

SELECT 
     A.*, 
     PreQuery.CommonResources 
    from 
     (SELECT 
       ra2.author_id, 
       COUNT(*) as CommonResources 
      FROM 
       resources_authors ra1 
       JOIN resources_authors ra2 
        ON ra1.resource_id = ra2.resource_id 
        AND NOT ra1.author_id = ra2.author_id 
      WHERE 
       ra1.author_id = 1313 
      GROUP BY 
       ra2.author_id) PreQuery 
     JOIN authors A 
     ON PreQuery.author_id = A.author_id 
+0

그건 멋지 네요. 내 실제 데이터에서 쿼리 시간은 0.55 초에서 0.01 초로 줄었습니다. 나는 여전히 쿼리에 대해 머리를 쓰고 있는데, 최적화하려고하는 다른 쿼리에 대해서는 의미가 있지만, 올바르게 이해했다면 중요한 단계는 WHERE 절이 기본 테이블의 필드를 사용했는지 확인하는 것이 었습니다. 조인 된 테이블이 아니라 테이블 스캔을 제거합니다. –

+0

@MarkBarnes, 예, 저는 귀하의 질문에 대한 BASELINE을 시작했습니다. 한 저자 (여러 오퍼에 관심이 있다면 여러 개, IN (목록))를 사용하십시오.그런 다음 동일한 리소스에 대한 조인을 추가하여 다른 모든 사람에게 (원래 작성자 포함) 제공하지만 원본 작성자의 NOT은 최종 세트에서 벗어납니다. – DRapp

+0

@MarkBanes, btw, 다른 쿼리가 있으면 여기로 던져 버리고 그냥 나를 쳐다보세요. – DRapp

관련 문제