2014-10-10 4 views
1

1 : 1 왼쪽 조인을 수행하는 관계가 1 인 테이블이 두 개 있습니다. 쿼리가 올바른 결과를 반환하지만 느린 쿼리 로그에 표시됩니다 (최대 5 초 소요). 이 쿼리를 작성하는 더 좋은 방법이 있습니까? 1 대 다수 관계가있는 테이블에서 1 대 1 왼쪽 조인을 수행하는 가장 빠른 방법 (MySQL)

select * from 
tablea a left join tableb b 
    on a.tablea_id = b.tablea_id 
    and b.tableb_id = (select max(tableb_id) from tableb b2 where b2.tablea_id = a.tablea_id) 

즉 나는 가장 큰 tableb_idTableB에 행에 결합 TableA 왼쪽 싶습니다.

TableA 
tablea_id 
1 
2 

TableB 
tableb_id, tablea_id, data 
1, 1, x 
2, 1, y 

Expected Result 
tablea_id, tableb_id, data 
1, 2, y 
2, null, null 

는 TableA의 tablea_id에 인덱스를 갖고 TableB의 tablea_id,tableb_id는의 지수를 갖는다.

부질 TableB의 각 행에 대해 실행지고 상관

+----+--------------------+---------------+--------+-----------------+---------------+---------+----------------------+-------+-------------+ 
| id | select_type  | table   | type | possible_keys | key   | key_len | ref     | rows | Extra  | 
+----+--------------------+---------------+--------+-----------------+---------------+---------+----------------------+-------+-------------+ 
| 1 | PRIMARY   | c    | index | NULL   | department_id | 4  | NULL     | 18966 | Using index | 
| 1 | PRIMARY   | recent_cv_lut | eq_ref | PRIMARY,case_id | PRIMARY  | 4  | func     |  1 |    | 
| 2 | DEPENDENT SUBQUERY | cases_visits | ref | case_id   | case_id  | 4  | abcd_records_v2.c.id |  2 | Using index | 
+----+--------------------+---------------+--------+-----------------+---------------+---------+----------------------+-------+-------------+ 
+0

tablea와 tableb에 몇 개의 행이 있습니까? 테이블의 DDL도 게시 할 수 있습니까? –

+0

@AntoanMilkov tablea에는 20,000 개의 레코드가 있고 tableb에는 60,000 개의 레코드가 있습니다. 죄송합니다, ddl을 게시 할 수는 없지만 언급 된 모든 ID 열은 정수입니다. – FuzzyTree

+0

nulls가 실제로 필요합니까? :) –

답변

3

가능성 출력을, 설명한다.

인라인 뷰 쿼리를 사용하는 것이 더 효율적일 수 있습니다

(의 출력 우리가 정말 적절한 인덱스를 사용할 수 있는지에 관한 추측하고 있으며, MySQL은 그 활용하면, 설명한다. 없음) 한 번에 각 tablea_id에 대해 최대 tableb_id 값을 가져온 다음 조인 작업을 사용합니다. 다음과 같이 입력하십시오 :

SELECT a.* 
    , b.* 
    FROM tablea a 
    LEFT 
    JOIN (SELECT n.tablea_id 
       , MAX(n.tableb_id) AS max_tableb_id 
      FROM tableb n 
      GROUP 
      BY n.tablea_id 
     ) m 
    ON m.tablea_id = a.tablea_id 
    LEFT 
    JOIN tableb b 
    ON b.tablea_id = m.tablea_id 
    AND b.tableb_id = m.max_tableb_id 

대체 방법이지만 더 빠른 것으로 보장 할 수는 없습니다. 그것은 정말로 우리가 어떤 정보도 가지고 있지 않은 모든 일들에 달려 있습니다. 대안으로


편집

(행, 기수, 데이터 유형, 사용 가능한 인덱스 등의 수), 우리는 인라인보기에 TABLEA와 TableB의 사이에 가입 할 수 있습니다. 이로 인해 성능이 향상 될 수 있습니다. (다시 말하지만, 실제로 정보가없는 많은 것에 달려 있습니다.)

SELECT m.tablea_id 
    , m.foo 
    , b.* 
    FROM (SELECT a.tablea_id 
       , a.foo 
       , MAX(n.tableb_id) AS max_tableb_id 
      FROM tablea a 
      LEFT 
      JOIN tableb n ON n.tablea_id = a.tablea_id 
      GROUP 
      BY a.tablea_id 
     ) m 
    LEFT 
    JOIN tableb b 
    ON b.tablea_id = m.tablea_id 
    AND b.tableb_id = m.max_tableb_id 
+0

프로덕션 코드에서 사용하지 않을 select *를 사용하는 것 외에는 이것이 제가 생각하는 올바른 접근 방법입니다. – HLGEM

+0

이 쿼리는 더 적은 수의 행을 반환합니다. 내부 조인이 tableb에 항목이없는 tablea의 행을 제외하는지 궁금합니다. 내부 조인을 왼쪽 조인으로 변경하려고 시도했지만 20 초 후에 쿼리를 중단했습니다. – FuzzyTree

+0

@FuzzyTree : 예, 정확하게. 그건 내 잘못이야. 외부 조인 이었어 야 했어. LEFT 키워드를 놓쳤습니다. (나는 그것을 추가하기 위해 편집 할 것입니다.) – spencer7593