다음은 최근에 직장에서 발생한 시나리오입니다.
A, B, C의 세 테이블을 고려하십시오.
A에는 3,000 개의 행이 있습니다. B에는 300,000,000 개의 행이 있습니다. C에는 2,000 개의 행이 있습니다.
외래 키는 B (a_id), B (c_id)로 정의됩니다.
다음과 같은 쿼리가 있다고 가정합니다.
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
내 경험상 MySQL은이 경우 C-> B-> A로 이동할 수 있습니다. C는 A보다 작고 B는 거대하며 모두 동등 조인입니다.
문제는 MySQL이 (C.id와 B.c_id) 대 (A.id와 B.a_id) 사이의 교차점 크기를 반드시 고려하지 않는다는 것입니다. B와 C 사이의 조인이 B만큼 많은 행을 반환하는 경우 매우 잘못된 선택입니다. A로 시작하여 B를 A만큼 많은 행으로 필터링했다면 훨씬 더 나은 선택이었을 것입니다. straight_join이 명령을 다음과 같이 강제하는 데 사용할 수 있습니다.
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
이제 a이전에에 가입해야합니다 b.
일반적으로 결과 집합의 행 수를 최소화하는 순서로 조인을 수행하려고합니다. 따라서 작은 테이블로 시작하여 결과 조인도 작아 지도록 조인하는 것이 이상적입니다. 작은 테이블에서 시작하여 더 큰 테이블에 결합하면 큰 테이블만큼 커지면 모든 것이 배 모양이됩니다.
하지만 통계에 따라 다릅니다. 데이터 분포가 변경되면 계산이 변경 될 수 있습니다. 또한 결합 메커니즘의 구현 세부 사항에 따라 다릅니다.
필자가 본 최악의 경우는 필수 straight_join이거나 공격적인 인덱스 힌팅을 제외하고는 모두 가벼운 필터링을 사용하여 엄격한 정렬 순서로 많은 데이터에 페이지를 매기는 쿼리입니다. MySQL은 정렬보다 필터 및 조인에 인덱스를 사용하는 것을 강력히 선호합니다. 이는 대부분의 사람들이 전체 데이터베이스를 정렬하려고하는 것이 아니라 쿼리에 응답하는 행의 제한된 하위 집합을 가지고 있기 때문에 이치에 맞습니다. 그리고 제한된 하위 집합을 정렬하는 것이 정렬 여부에 관계없이 전체 테이블을 필터링하는 것보다 훨씬 빠릅니다. 아니. 이 경우 인덱싱 된 열이있는 테이블 바로 뒤에 스트레이트 조인을 넣어 고정 된 항목으로 정렬하고 싶었습니다.
straight_join.