JOIN 조건과 WHERE 조건 사이에 실행 차이가 있습니까?


17

이 두 예제 쿼리간에 성능 차이가 있습니까?

쿼리 1 :

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y'

쿼리 2;

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
   and b.tag = 'Y'

유일한 차이점은 보충 조건의 배치입니다. 첫 번째는 WHERE절을 사용 하고 두 번째는 조건을 ON절에 추가합니다 .

Teradata 시스템에서 이러한 쿼리를 실행하면 Explain 계획이 동일하며 JOIN 단계는 각 경우에 추가 조건을 표시합니다. 그러나 MySQL에 관한 이 SO 질문 에 대한 답변 중 하나 WHERE는 조인이 이루어진 후 처리가 발생 하기 때문에 두 번째 스타일이 선호된다는 것을 제안했습니다 .

이와 같은 쿼리를 코딩 할 때 따라야 할 일반적인 규칙이 있습니까? 분명히 데이터베이스에 아무런 영향을 미치지 않기 때문에 플랫폼에 의존해야한다고 생각하지만 아마도 Teradata의 기능 일 것입니다. 이 경우 입니다 플랫폼에 의존, 나는 몇 가지 문서 참조를 얻기 위해 매우 싶습니다; 나는 무엇을 찾아야할지 정말로 모른다.


9
RDBMS 옵티마이 저가 구문 분석 및 최적화를 처리하는 방법에 따라 다르므로 플랫폼에 따라 다릅니다.
Philᵀᴹ

8
그리고 관련된 질문에 대한 대답은 몇 가지 다운 보트가 필요합니다. MySQL의 프리미티브 옵티 마이저조차도 이러한 간단한 쿼리는 동일하며 "모든 조인이 이루어진 후 WHERE 절이 평가된다" 는 것은 실제 실행이 아니라 논리적 수준에서만 사실이라는 것을 이해합니다.
ypercubeᵀᴹ

1
실제로 복제본이 아닙니다. 그 질문과 답변은 "암시 적"과 "명시 적"JOIN 구문을 비교하고있었습니다. 보충 가입 조건에 대해 구체적으로 묻습니다.
BellevueBob

이전에 시도했지만 많은 다운 투표를 받았으므로 답변에 게시물을 감히하지 않을 것입니다. 조인이 많을 때 조건을 조인으로 가져 와서 더 나은 쿼리 계획 (초기 필터링)을 경험 한 사례가 있습니다. 여전히 같은 결과입니다.
paparazzo

답변:


14

Sasha Pachev의 MySQL 내부 이해하기 172 페이지 9 장 (파서 및 최적화 프로그램)에 따르면

MySQL 내부 이해

다음은 다음과 같은 쿼리 평가 분석입니다.

  • 테이블에서 레코드를 검색하는 데 사용할 수있는 키를 결정하고 각 테이블에 가장 적합한 키를 선택하십시오.
  • 각 테이블에 대해 키를 읽는 것보다 테이블 스캔이 더 나은지 여부를 결정하십시오. 키 값과 일치하는 레코드가 많으면 키의 장점이 줄어들고 테이블 스캔이 더 빨라집니다.
  • 쿼리에 둘 이상의 테이블이있을 때 테이블이 조인되는 순서를 결정하십시오.
  • WHERE 절을 다시 작성하여 데드 코드를 제거하고 불필요한 계산을 줄이고 가능한 경우 키를 사용하는 방법을 열 수 있도록 제약 조건을 변경하십시오.
  • 조인에서 사용하지 않는 테이블을 제거하십시오.
  • ORDER BY및에 키를 사용할 수 있는지 확인하십시오 GROUP BY.
  • 서브 쿼리를 단순화하고 결과를 캐시 할 수있는 정도를 결정하십시오.
  • 뷰 병합 (뷰 참조를 매크로로 확장)

같은 페이지에 다음과 같이 표시됩니다.

MySQL 최적화 용어에서 모든 쿼리는 조인 집합입니다. 여기서 join 이라는 용어 는 SQL 명령보다 더 광범위하게 사용됩니다. 하나의 테이블에 대한 쿼리는 퇴화 조인입니다. 일반적으로 하나의 테이블에서 레코드를 조인으로 읽는 것을 생각하지 않지만 기존의 조인에 사용 된 동일한 구조와 알고리즘은 하나의 테이블만으로 쿼리를 해결하기 위해 완벽하게 작동합니다.

발문

존재하는 키, 데이터 양 및 쿼리의 표현으로 인해 MySQL Joins는 때때로 우리 자신의 이익을 위해 일하거나 (또는 ​​우리를 다시 방문하기 위해) 예상하지 않았고 신속하게 설명 할 수없는 결과를 얻을 수 있습니다.

나는 전에이 기발함에 대해 썼다.

MySQL Query Optimizer는 쿼리 평가 중에 특정 키를 닫을 수 있기 때문입니다.

@Phil의 의견은이 답변을 게시하는 방법을 알려줍니다 (@Phil의 의견에 +1)

@ypercube의 의견 (이것도 +1)은 MySQL의 Query Optimizer가 원시이기 때문에 내 게시물의 컴팩트 버전입니다. 불행히도 외부 스토리지 엔진을 다루기 때문입니다.

결론

실제 질문과 관련하여 MySQL Query Optimizer는 각 쿼리의 수행 메트릭을 결정합니다.

  • 행을 계산
  • 키 선택
  • 간헐적 결과 세트 마사지
  • 예, 실제 가입

쿼리를 다시 작성 (리팩토링)하여 실행 순서를 강제해야 할 수 있습니다.

여기 당신이 준 첫 번째 쿼리가 있습니다

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y';

WHERE를 먼저 평가하려면 다시 작성하십시오.

select count(*)
from   table1 a
join   (select key_col from table2 where tag='Y') b
on     b.key_col=a.key_col;

그것은 분명히 EXPLAIN 계획을 바꿀 것입니다. 더 나은 결과를 얻을 수 있습니다.

한 번이 기술을 적용한 StackOverflow의 질문에 대답했습니다. EXPLAIN은 끔찍했지만 성능은 다이나마이트였습니다. 올바른 인덱스가 있고 하위 쿼리에서 LIMIT를 사용했기 때문에 작동했습니다 .

주가와 마찬가지로 쿼리와 관련하여이를 표현하려고 할 때 제한이 적용되고 결과가 다를 수 있으며 과거 성과가 미래 결과를 나타내는 것은 아닙니다.


2
자세한 MySQL 관련 정보와 특히 "Epilogue"와 "Conclusion"의 차이점을 배우도록 속이는 데 도움이되는 +1!
BellevueBob

필자의 글에서 에필로그는 하위 결론입니다.
RolandoMySQLDBA

6
@Rolando : 최신 MariaDB (5.3 및 5.5) 버전과 최근에 출시 된 기본 MySQL (5.6) 버전에서 최적화 프로그램의 개선 사항에 대한 여파 를 추가 할 수 있습니다 . 다시 쓰기를 불필요하게 만들 수 있습니다.
ypercubeᵀᴹ

1

Oracle의 경우 mySQL에 긴 설명이 있으므로 최적화 프로그램을 활용하는 두 가지 높은 수준의 방법이 있습니다.

첫 번째는 규칙 기반 최적화 (또는 RBO)입니다. 오라클은 15 개의 set-in-stone 규칙을 가지고 있으며, 각 쿼리는 정해진 순서대로 따르려고 시도합니다. 규칙 1에서 최적화 된 쿼리를 생성 할 수 없으면 규칙 2에 도달 한 후 규칙 15에 도달 할 때까지 계속 진행합니다.

자세한 정보 : https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm

이는 비용 기반 최적화 프로그램 (일명 CBO)으로 변환되지 않은 11.1 이하의 Oracle RDBMS 커널에 영향을줍니다. Oracle 11.2 이상에는 CBO 옵티마이 저가 필요하지만 사용자가 원할 경우 특정 Rql ID를 기존 RBO 방법으로 최적화 할 수 있습니다.

Oracle 11.1+ 용 CBO는 동일한 SQL ID에 대해 여러 개의 실행 계획을 작성하고 전체 예상 비용이 가장 적은 계획을 실행합니다. RBO의 많은 로직을 활용하지만 테이블 통계를 분석하여 DB가 최종 사용자에게 데이터를 제공하기 위해 수행해야하는 각 작업에 대한 동적 실행 계획 비용을 생성합니다. 매우 큰 테이블에서 전체 테이블 스캔을 실행하면 비용이 많이 듭니다. 행이 10 개인 테이블에서 전체 테이블 스캔을 실행하는 것이 저렴합니다. RBO에서 이들은 동일한 작업으로 간주되었습니다.

자세한 정보 : https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics

특정 쿼리 예제의 경우 : Oracle은 정보를 분석하여 다른 실행 계획을 세우므로 기술적으로 다른 계획보다 낫습니다. 그러나 이것은 최소한의 차이 일 수 있습니다. Oracle RBO와 CBO는 더 적은 조건에서 조인에서 실행되고 조인으로 만든 임시 테이블에서 특정 열을 필터링하기 때문에 쿼리 1을 더 원합니다.


1

두 개의 쿼리가 있고 동일한 쿼리라고 생각되면 다음이 발생할 수 있습니다.

  1. 두 쿼리 모두 동일한 실행 계획이 있습니다. 괜찮습니다. 우리가 기대하는 것입니다. 이것이 쿼리에 대한 최적의 실행 계획이 되길 바랍니다.
  2. 다른 실행 계획이 있습니다. 여기에 두 개의 하위 사례가 있습니다.

    2.1 쿼리마다 실행 계획이 다르지만 두 계획 모두 동일하게 수행됩니다. 그것도 괜찮습니다. 동등한 쿼리에 대해 동일한 계획을 생성해야 할 필요는 없습니다. 그러나 성능은 동일해야합니다. 그리고 우리는 그것이 최선이되기를 바랍니다.

    2.2 쿼리마다 실행 계획이 다르며 한 계획이 다른 계획보다 낫습니다. 다시 우리는 하위 사례가 있습니다.

    2.2.1 쿼리가 같지 않기 때문에 계획이 다릅니다. 그래서 그들이 실제로 동등한 지주의 깊게 확인하십시오. 귀하의 경우에 그들은 실제로 동등합니다.

    2.2.2 계획은 다르지만 쿼리는 동일합니다. 이는 옵티마이 저가 충분히 성숙되지 않았 음을 의미합니다. 완벽한 옵티마이 저가있는 완벽한 세상에서는 이런 일이 발생하지 않아야합니다. 예, 플랫폼에 따라 다르며, 왜 이런 일이 발생하는지 알아 보려면 플랫폼 별 문서를 연구해야합니다.

    2.2.3 계획이 다르고 쿼리가 동일하며 데이터베이스 소프트웨어에 버그가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.