2016-07-20 2 views
1

기본적으로 두 테이블의 행을 조인해야하는 쿼리를 작성해야한다. 내 초기 쿼리는 다음과 같습니다조인 조건에서 디코드를 사용할 때 쿼리 속도가 느리다.

select * 
    from Table1 T1 
    left join Table2 T2 on T1.f1 = T2.f1 
        and (decode(T2.f2, 
           '1', 
           'value1', 
           '2', 
           'value2', 
           '3', 
           'value3') = T1.f2 or T2.f2 = '4') 

내가 뭘 트링하고 직접적 조인 조건으로 사용할 수있는 두 개의 필드 (T1.f1, T2.f1)하지만, 일부를 필요로 다른 두 개의 필드가 Table1Table2입니다 이 두 열의 값에 동일한 값 집합이 없기 때문에 조인 조건에서 사용되기 전에 변환을 수행해야합니다.

이제이 쿼리는 실제로 느리게 실행됩니다. 전체를 제거하려고했습니다.

and (decode(T2.f2, 
          '1', 
          'value1', 
          '2', 
          'value2', 
          '3', 
          'value3') = T1.f2 or T2.f2 = '4') 

조건이며 정상적으로 실행됩니다.

left join Table2 T2 on T1.f1 = T2.f1 
       and (decode(T2.f2, 
          '1', 
          'value1', 
          '2', 
          'value2', 
          '3', 
          'value3') = T1.f2) 

을하고 또한 확인을 실행 : 그럼이 T2.f2 = '4' 부분을 제거하는 노력, 즉, 조건은 다음과 같습니다. 그렇다면 쿼리를 수정하여 (물론 원본과 동일한 결과를 얻음) 쿼리를 빠르게 실행해야합니까? 실행을 무엇을 잡고 있습니까?

+0

두 버전의 쿼리에 대한 Explain 플랜을 게시 할 수 있습니까? – MT0

답변

0

당신은 절에 사용할 수있는 (또한 materialize 힌트)

WITH 
    T2 AS 
(
     select /*+ materialize */ 
    decode(table2.f2, 
         '1', 
         'value1', 
         '2', 
         'value2', 
         '3', 
         'value3', 
         '4', 
         T1.f2) as join_sttmnt 
    , Table2.* 
from table2 
) 
select * 
    from Table1 T1 
    left join T2 on T1.f1 = T2.f1 
        and (join_sttmnt = T1.f2 or T2.f2 = '4') 

내가 한 그것을 시도하지 마라. 그러나 논리는 사실이다.

+0

왜 아래 투표? 이것은 지금까지 나를위한 작업 솔루션입니다. 다른 의견에 언급했듯이 다른 솔루션은 여전히 ​​내 테스트가 느립니다. 임시 테이블 사용에 대해서는별로 신경 쓰지 않습니다. 하루 종일 한 번 실행되는 작업에서이 쿼리를 사용할 것이기 때문입니다. – tete

+0

분명히 당신이 아닙니다. 누군가 당신의 대답에 투표했습니다. 나에게 그것은 실용적인 해결책이다. – tete

+0

정답으로 진드기를 넣을 수 있습니까? –

0

이것 좀보세요 : 그 속도를 수있는 디코드 조건으로 T2.f2 = '4' 조건을 혼합,

Is having an 'OR' in an INNER JOIN condition a bad idea?

또는 :

(ORACLE 참조하지 않는 이전 게시물 업데이트) , 비록 내가 그것을 테스트하지 않았습니다. 다음과 같이 표시됩니다.

left join Table2 T2 on T1.f1 = T2.f1 
      and (decode(T2.f2, 
         '1', 
         'value1', 
         '2', 
         'value2', 
         '3', 
         'value3', 
         '4', 
         T1.f2) = T1.f2) 

이 정보가 도움이되기를 바랍니다.

+0

이것은 완전히 다른 논리입니다 - 이것은 OP의 솔루션이 'T1'과 일치하는 반면 'OR (T1.f2 ='4 'AND T2.f2 NOT IN ('값 1 ','값 2 ','값 3 '))입니다. f2 = '4 ''이고'T2.f2'는 임의의 값을가집니다. – MT0

+0

또한 링크 된 질문은 SQL Server (오라클이 아님)와 5 년 전 (데이터베이스가 여러 버전으로 이동 한 이후)입니다. 올바른 RDBMS에 대한 최신 참조를 가지고 있습니까? – MT0

+0

내가 명백한 것이 빠진다면 죄송하지만 OP의 논리는 'T12.f2 ='4 '가 아니라'T2.f2 = '4' '와 일치해야합니다. – Russop

1

DECODE(...) (또는 함수)을 사용하면 오라클은 해당 열에서 색인을 사용할 수 없으며 테이블 스캔을 수행합니다.

당신은 함수 기반 인덱스를 만들 수 있습니다 또는 당신이 기능이없는 쿼리를 다시 작성 시도 할 수 있습니다 :

LEFT OUTER JOIN 
Table2 T2 
ON ( T1.f1 = T2.T1 
    AND ( (T1.f2 = 'value1' AND T2.f2 = '1') 
     OR (T1.f2 = 'value2' AND T2.f2 = '2') 
     OR (T1.f2 = 'value3' AND T2.f2 = '3') 
     OR (      T2.f2 = '4') 
     ) 
    ) 
+0

'ON (T1.f1 = T2.T1 AND (T1.f2 ='value1 'AND T2.f2 ='1 '))'을 실행하면 빠르게 실행되지만'켜기 '(T1.f1 = (T1.f2 = 'value1'AND T2.f2 = '1') OR (T1.f2 = 'value2'AND T2.f2 = '2')))'다시 느리게 됨 – tete

관련 문제