문제

다음 양식과 유사한 SQL 쿼리를 사용하고 있습니다.

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
AND table1.period = table2.period

그리고 너무 느리게 또는 무언가가 너무 느리거나 교착 상태가되기 때문에 4 분 이상 돌아 오기 때문에 교착 상태입니다. 내가 이것으로 바꾸면 :

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
WHERE table1.period = table2.period

그런 다음 잘 작동합니다 (올바른 수의 열을 반환하지는 않지만). 이것을 속도를 높이는 방법이 있습니까?

업데이트: 후자의 쿼리의 마지막 두 줄을 전환하는 경우에도 마찬가지입니다.

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.period = table2.period
WHERE table1.person_uid = table2.person_uid

UPDATE 2: 이것들은 실제로 내가 참여한 견해입니다. 불행히도, 그들은 제어 할 수없는 데이터베이스에 있으므로 인덱싱을 쉽게 변경할 수 없습니다. 나는 이것이 색인 문제라는 데 동의하는 경향이있다. 내가 모르는이 쿼리를 조정하는 마법의 방법이있는 경우에 대답을 수락하기 전에 잠시 기다릴 것입니다. 그렇지 않으면, 나는 현재 답변 중 하나를 받아들이고 내가하고 싶은 일을 할 수있는 다른 방법을 알아 내려고 노력할 것입니다. 지금까지 모두의 도움에 감사드립니다.

도움이 되었습니까?

해결책

진술 2와 3은 첫 번째 진술과 다르다는 것을 명심하십시오.

어떻게? 글쎄, 당신은 왼쪽 외부 조인을하고 있는데, 당신의 위치는 (on clause와 같이) 그것을 고려하지 않습니다. 최소한으로 시도하십시오.

SELECT col1, col2
FROM table1, table2
WHERE table1.person_uid = table2.person_uid (+)
AND table1.period = table2.period (+)

동일한 성능 문제가 있는지 확인하십시오.

이 테이블에 어떤 색인이 있습니까? 이 관계는 외국의 주요 제약으로 정의됩니까?

아마도 필요한 것은 person_uid와 기간 (두 테이블 모두)의 복합 색인입니다.

다른 팁

마지막 두 가지가 첫 번째 쿼리가 아닌 이유를 이해해야한다고 생각합니다. 왼쪽 조인을 수행 한 다음 조인 오른쪽에있는 테이블에 필드를 참조하는 where 절 (첫 번째 테이블과 일치하는 레코드가 없을 수 있음)을 추가하면 조인을 효과적으로 변경했습니다. 내부 조인. 이것에 대한 예외가 하나 있는데, 당신이 다음과 같은 것을 언급하는 경우

SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
WHERE table2.person_uid is null

이 경우 두 번째 테이블에 레코드가없는 레코드를 요구합니다. 그러나이 특별한 경우를 제외하고, 당신은 where 절의 표 2의 필드를 반박하면 왼쪽 조인을 내부 조인으로 변경하고 있습니다.

쿼리가 충분히 빠르지 않으면 인덱싱을 살펴 보겠습니다.

당신이 제공 한 정보를 기반으로 누구나 당신에게 말하는 것은 추측입니다.

쿼리의 실행 계획을보십시오. 계획에 속도가 느려질 이유가 없다면 여기 계획이 게시됩니다.

http://download.oracle.com/docs/cd/b28359_01/server.111/b28274/ex_plan.htm#pfgrf009

덮개 색인이 있습니까? person_uid 그리고 period 두 테이블 모두?

그렇지 않은 경우 추가하고 다시 시도하십시오.

실행 계획을 살펴보고 쿼리가 실제로 무엇을하고 있는지 확인하십시오.

또한 : 필드의 데이터 유형은 무엇입니까? 두 테이블에서 동일합니까? 암시 적 캐스트는 실제로 속도를 늦출 수 있습니다.

이 테이블에 합류하는 열에 인덱스가 있습니까? Oracle의 무료 SQLDeveloper 제품을 설치하고 해당 쿼리에서 "설명"을 수행하고 두 테이블의 순차적 스캔을 수행하는지 확인하십시오.

왼쪽 결합에서는 (person_uid, period)의 각 고유 한 조합에 대해 표 1을 스캔 한 다음 모든 해당 레코드를 검색합니다. 표 2에 적절한 색인이 없으면 해당 테이블 전체를 스캔하는 것도 포함될 수 있습니다.

실행 계획을 보지 않고 가장 좋은 추측은 첫 번째 쿼리 (올바른 것으로 보이는 유일한 쿼리)는 표 1뿐만 아니라 테이블 스캔을해야한다는 것입니다.

인덱스를 변경할 수 없다고 말하면 쿼리를 변경해야합니다. 내가 알 수있는 한, 현실적인 대안은 하나뿐입니다 ...

SELECT
   col1, col2
FROM
   table2
FULL OUTER JOIN
   table1
      ON table1.person_uid = table2.person_uid
      AND table1.period = table2.period
WHERE
   table1.person_uid IS NOT NULL

여기서 희망은 (person_uid, 기간)의 각 고유 한 조합에 대해 표 2를 스캔하지만 표 1의 인덱스를 사용하기를 희망합니다. (표 1을 스캔하고 표 2에서 인덱스를 사용하는 것과는 반대로 쿼리에서 기대했던 것.)

그러나 표 1이 적절한 색인이 없다면 성능 향상을 전혀 볼 가능성이 거의 없습니다 ...

뎀스.

업데이트 중 하나에서 OP는 실제로 테이블이 아닌보기를 쿼리하고 있다고 명시합니다. 이 경우, 특히 뷰가 복잡하고 필요한 정보가 포함되어 있지 않은 다른 많은 테이블에 가입하거나 뷰를 호출하는 뷰 인 경우 필요한 테이블을 직접 쿼리함으로써 성능이 향상 될 수 있습니다.

ANSI Join Syntax는 결합 조건과 필터 홍보간에 매우 명확한 차이를 제공합니다. 이것은 외부 조인을 작성할 때 매우 중요합니다. EMP/Dept 테이블을 사용하여 다음 두 개의 외부 조인의 결과를보십시오.

Q1

SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
LEFT OUTER JOIN emp e
on  d.deptno = e.deptno
and loc in ('NEW YORK','BOSTON' )
;

DNAME              DEPTNO ENAME             MGR LOC
-------------- ---------- ---------- ---------- -------------
ACCOUNTING             10 CLARK            7839 NEW YORK
ACCOUNTING             10 KING                  NEW YORK
ACCOUNTING             10 MILLER           7782 NEW YORK
RESEARCH               20                       DALLAS
SALES                  30                       CHICAGO
OPERATIONS             40                       BOSTON

====

Q2
SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
LEFT OUTER JOIN emp e
on  d.deptno = e.deptno
where loc in ('NEW YORK','BOSTON' )
;

DNAME              DEPTNO ENAME             MGR LOC
-------------- ---------- ---------- ---------- -------------
ACCOUNTING             10 CLARK            7839 NEW YORK
ACCOUNTING             10 KING                  NEW YORK
ACCOUNTING             10 MILLER           7782 NEW YORK
OPERATIONS             40                       BOSTON

첫 번째 예, Q1은 "상수에 가입"의 예입니다. 기본적으로, 필터 조건은 외부 조인을 수행하기 전에 적용됩니다. 따라서 행을 제거하고 이후 외부 조인의 일부로 다시 추가됩니다. 반드시 잘못된 것은 아니지만 실제로 요청한 쿼리입니까? 종종 (외부) 조인 후 필터가 적용되는 곳에서 필요한 Q2에 표시된 결과입니다.

대규모 데이터 세트의 경우에도 성능에 영향을 미칩니다. 많은 경우에, 상수에 가입하는 것은 측면보기를 만들어 최적화에 의해 내부적으로 해결되어야하며, 일반적으로 해시 조인이 아닌 중첩 루프 조인을 통해서만 최적화 할 수 있습니다.

Oracle Outer Join 구문에 익숙한 개발자의 경우 쿼리가 다음과 같이 작성되었을 것입니다.

SELECT dname, d.deptno, e.ename, e.mgr, d.loc
FROM dept d
        ,emp e
where  d.deptno = e.deptno(+)
and loc in ('NEW YORK','BOSTON' )

이 쿼리는 의미 적으로 위의 Q2와 동일합니다.

따라서 요약하면 ANSI 외부 조인을 작성할 때 조인 절과 WHERE 절의 차이를 이해하는 것이 매우 중요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top