2017-05-08 5 views
1

이 질문에 100 번이나 물었습니다.이 질문은 "어떻게해야합니까?"가 아니라 효율적인 질문입니다 - 많이 알지 못하는 주제입니다. 약."가장 최근 행"에 참여하는 가장 효율적인 방법

제 인터넷 읽기에서 저는 매우 효율적이라고 들리는 가장 최근의 문제를 해결하는 한 가지 방법을 생각해 냈습니다 - 일치 조건에 따라 그룹화 된 "최대"테이블을 왼쪽으로 조인 한 다음 LEFT JOIN과 일치하는 행을 찾습니다 그룹화 된 조건. 다음과 같은 내용 :

Select employee.*, evaluation.* form employee 
LEFT JOIN (select max(report_date) report_date, employee_id 
     from evaluation group by employee_id) most_recent_eval 
    on most_recent_eval.employee_id = employee.id 
LEFT JOIN evaluation 
    on evaluation.employee_id = employee.id and evaluation.report_date = most_recent_eval.report_date 

내가 모르는 문제가 있습니까? 이것은 2 개의 테이블 스캔을하고 있습니까? (하나는 최대 값을, 하나는 행을 찾으려고합니다)? 모든 직원에 대해 전체 스캔을 2 회해야합니까?

내가 가장 최근에 행 (평가, 보안 정리 및 프로젝트)이 필요한 3 개의 테이블에 참여하고 있으며 비효율적 인 부분이 대량으로 늘어나는 것처럼 보입니다.

아무에게도 이것에 대한 조언을 줄 수 있습니까?

+0

'explain select ...'를 실행하여 질의가 무엇인지 확인할 수 있습니다. 질문. MySQL 웹 사이트에 결과를 해석하는 방법에 대한 자세한 지침이 있습니다. Explain 결과가 없으면 조회의 효율성을 알 수 없습니다. – Shadow

+0

이것은 단순화 된 예제이며 많은 관련성없는 열을 포함하고있는 실제 쿼리의 출력으로 문제를 해결하지 않으려 고합니다. 저는 "가장 최근의"조인 문제를 해결하는 다양한 방법의 효율성에 대한 좀 더 일반적인 지침을 찾고 있습니다.이제 설명 출력에 관한 책을 열어서, 그 포인터에 대해 고맙습니다. – whiteatom

+0

Explain 결과를 살펴보면 가장 최근의 평가판이 파생 테이블에 대한 데카르트 조인 (조인 유형 아래에 ALL 표시)을 수행하는 것이 나의 하위 쿼리로 나타납니다. start_date에 대한 인덱스가 있습니다. 사용하면 안됩니까? – whiteatom

답변

0

제안하는 쿼리 패턴을 사용하면 꽤 좋은 모양이어야합니다.

가능한 한 가지 제안은 evaluation 테이블에 자체 증가 열 id 열이있는 경우 도움이됩니다. 당신은 다음과 같이 조인 다음

  SELECT MAX(id) id 
       FROM evaluation 
      GROUP BY employee_id 

: 당신 이 하위 쿼리와 각 직원에 대한 최신 평가를 찾을 수 있습니다

 FROM employee 
    LEFT JOIN (
       SELECT MAX(id) id 
       FROM evaluation 
       GROUP BY employee_id 
      ) most_recent_eval ON most_recent_eval.employee_id=employee.id 
    LEFT JOIN evaluation ON most_recent_eval.id = evaluation.id 

이 작동을 경우 id 값과 report_dateevaluation 테이블의 값은 같은 순서입니다. 귀하의 신청서에 해당되는 경우 귀하 만 알 수 있습니다. 그러나 그렇다면 이것이 매우 유용한 최적화입니다.

이외에도 쿼리 속도를 높이려면 일부 테이블에 복합 인덱스를 추가해야 할 수도 있습니다. 먼저 올바르게 작동하도록하십시오. http://use-the-index-luke.com/을 읽으십시오. 많은 수의 단일 컬럼 인덱스는 특정 쿼리를 가속화하지 않는 한 일반적으로 MySQL 쿼리 성능에 해를 끼친다는 것을 기억하십시오.

당신이 (employee_id, report_date)에 복합 인덱스를 작성하는 경우,

select max(report_date) report_date, employee_id 
    from evaluation 
    group by employee_id 

loose index scan 놀랄만큼 효율적으로 만족 될 수있는이 하위 쿼리. 마찬가지로, 이노, 쿼리

  SELECT MAX(id) id 
       FROM evaluation 
      GROUP BY employee_id 

를 사용하는 경우하는 employee_id에 단일 열 인덱스에 느슨한 인덱스 스캔에 의해 만족 될 수있다. (MyISAM을 사용하고 있다면 에 복합 색인이 필요합니다. 왜냐하면 InnoDB가 모든 색인에 기본 키 열을 암시 적으로 넣기 때문입니다.)

+1

이 작업을 수행 할 때 여전히 도움이 필요하면 쿼리 성능에 대한 다른 질문을 고려하십시오. 먼저 쿼리 성능에 관한 부분을 먼저 읽어보십시오. http://meta.stackoverflow.com/a/271056/ –

+0

평가판을 순서대로 입력했는지 모르겠으므로 ID를 사용할 수 없지만 타임 스탬프를 사용하고 있습니다 (int (11) 열에서))를 사용합니다. 나는 use-the-index-luke.com에서 지금 읽고있다. .. 고마워. 내가 제공 한 링크에 제안 된대로 향후 성능 질문에 세부 정보를 추가하겠습니다. 나는 내가 사용하고있는 새로운 날짜 기반 테이블 구조를 사용하여 많은 새로운 쿼리를 작성하기 때문에 좀 더 일반적인 "올바른 방향"의 대답을 찾고 있다고 생각한다. – whiteatom

+0

'DATETIME' 및'TIMESTAMP' 데이터 항목은 정수와 마찬가지로 색인을 생성하기에 좋다는 것을 알아야합니다. 좋은 인덱싱 및 순서 지정 성능을 얻기 위해 부적절한 작업을 시간/날짜 값에 수행 할 필요가 없습니다. –