MySQL : 왼쪽 외부 조인과 내부 조인 중 어느 조인이 더 낫습니까?


11

모두 동일한 결과를 제공하는 경우 어떤 조인이 더 나은 성능을 발휘합니까? 예를 들어, 나는 두 개의 테이블을 가지고 employees(emp_id,name, address, designation, age, sex)work_log(emp_id,date,hours_wored). 일부 특정 결과를 얻을 모두 inner joinleft join동일한 결과를 제공합니다. 그러나 나는 여전히이 질문에만 국한되지 않는 몇 가지 의심을 가지고 있습니다.

  • 동일한 결과 값의 경우 어떤 조인이 더 효율적이며 선호합니까?
  • 가입 신청시 고려해야 할 다른 요소는 무엇입니까?
  • 내부 조인과 교차 조인 사이에 관계가 있습니까?

답변:


15

"더 나은"또는 "더 나쁜"조인 유형이 없습니다. 그것들은 다른 의미를 가지고 있으며 그것에 따라 사용되어야합니다.

귀하의 경우에는, 당신은 아마 더 work_log와 직원 (해당 테이블에 행을)하지 않으므로 LEFT JOINJOIN결과에 해당 될 것입니다. 그러나 그러한 일 (등록 된 work_log가없는 신입 사원)이있는 경우, JOIN직원은 해당 직원을 생략하고 왼쪽 조인 (첫 번째 테이블은 직원 임)은 모든 직원을 표시하고 work_log의 필드에는 널이 있습니다 (있는 경우) 일치하지 않습니다.

JOIN 유형에 대한 시각적 설명

다시 한 번, 성능은 정확성을 쿼리하는 두 번째입니다. 어떤 사람들은 당신이 LEFT JOINs를 사용해서는 안된다고 말합니다 . LEFT JOIN은 옵티마이 저가 특정 순서로 쿼리를 실행하도록하여 일부 최적화 (테이블 재정렬)를 방지하는 것은 사실입니다. 여기에 하나의 예가 있습니다. 그러나 INNER JOIN은 본질적으로 나쁘지 않기 때문에 정확성 / 의미가 희생되는 경우 다른 것을 선택하지 않아야합니다. 나머지 일반적인 최적화는 평소와 같이 적용됩니다.

요컨대, LEFT JOIN정말로 의미 하는 경우 사용하지 마십시오 INNER JOIN.

MySQL의에서 CROSS JOIN, INNER JOIN그리고 JOIN동일합니다. 표준에서, 의미 적, a는 CROSS JOIN이다 INNER JOIN없이 ON당신이 테이블 간의 행의 모든 조합을 얻을 수 있도록, 절.

당신은이 위키 백과에 참여하는 모든 의미 유형의 예를 . 실제로, MySQL은, 우리는 쓰기 만하는 경향이 JOINLEFT JOIN.


1
gr8 설명 @jynus. 운 좋게도 당신 에게서만 내 질문에 대한 답변을 얻었습니다.
ursitesion

1 관련 그래픽은 1000 단어보다 낫습니다. 당신은 그것을 했습니까?
Fr0zenFyr

아니, 난하지 않았다, 속성은 이미지의 하단에 codeproject.com/Articles/33052/... : 조인 나타내는 다이어그램 벤 사용하는 자사의 대수 형식화만큼이나 오래 만 - en.wikipedia.org/wiki/Relational_algebra
jynus

나는 일련의 의견을 시작한 다음 그것이 모두 귀결된다는 것을 깨달았습니다-그것은 당신의 질의에 달려 있습니다. 나에게서 +1!
iheanyi


0

모두 동일한 결과를 제공 할 경우 어떤 조인이 더 잘 수행됩니까?

이전 답변에 덧붙여 MySQL은 동일한 성능을 갖도록 최적화되었습니다.

예를 들어, 필터링 할 JOINvs LEFT JOIN+ WHERE절 과 같은 좋은 인덱스를 사용 하는 경우에도 마찬가지입니다. 최적화사람 읽기 는 많은 조인이있는 큰 쿼리에 적합합니다.

좋은 인덱스와 캐시를 사용하는 것이 더 중요합니다.

최적화 과정에 대한 자세한 설명은 여기를 참조하십시오.

쿼리 최적화 프로세스 : 쿼리는 여러 가지 방법으로 실행되어 동일한 결과를 생성 할 수 있습니다. 최적화 프로그램의 작업은 최상의 옵션을 찾는 것입니다.


0

MySql 5.7 8 vCPU, 52GB RAM은 동일하지 않습니다.

다음 쿼리는 ~ 30 초가 걸립니다. 이유는 확실하지 않습니다.

거래 테이블에는 24,257,151 개의 레코드가 있습니다.

활동 테이블에는 18,603,665 개의 레코드가 있습니다.

구매 테이블에는 13,911,705 개의 레코드가 있습니다.

필요한 모든 색인이 제자리에 있습니다

SELECT
    `trx`.`transaction_pk`,
    `trx`.`created`,
    `trx`.`updated`,
    `p`.`amount`,
    `trxst`.`name`,
    COALESCE ( a.units, 0 ) AS units
FROM
    `transaction` AS `trx`
    INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`
    left JOIN `activity` AS `a` ON `a`.`transaction_fk` = `trx`.`transaction_pk`
    LEFT JOIN `purchases` AS `p` ON `p`.`transaction_fk` = `trx`.`transaction_pk` 
WHERE
    `trx`.`entity_fk` IN ( 1234) 
    AND `trx`.`transaction_sub_type_fk` IN (
    2, 4, 5, 15, 16, 33, 37, 38, 85, 86, 87, 88, 102, 103 
    ) 
ORDER BY
    `trx`.`transaction_pk` DESC LIMIT 100 OFFSET 0;

다음 줄을 교체 한 후 :

INNER JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

LEFT JOIN으로

LEFT JOIN `transaction_sub_type` AS `trxst` ON  `trx`.`transaction_sub_type_fk`= `trxst`.`transaction_sub_type_pk`

같은 쿼리는 ~ 0.046s 걸립니다

전에 설명하십시오 :

1   SIMPLE  trxst       ALL PRIMARY             101 37.62   Using where; Using temporary; Using filesort
1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   transaction_sub_type_fk 4   trxst.transaction_sub_type_pk   2548    0.36    Using where
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 

다음에 설명하십시오 :

1   SIMPLE  trx     ref transaction_sub_type_fk,entity_fk   entity_fk   4   const   81474   83.65   Using where
1   SIMPLE  trxst       eq_ref  PRIMARY PRIMARY 4   trx.transaction_sub_type_fk 1   100 
1   SIMPLE  a       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
1   SIMPLE  p       ref transaction_fk  transaction_fk  4   trx.transaction_pk  1   100 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.