where조건이 실행되는 순서가 궁금합니다. 0 5 1,031

by alues [2016.12.20 11:30:47]


Atable 키 A1, A2, A3

Btable 키 B1, B2, B3

Ctable 키 C1

SELECT * 
FROM ATABLE A,
     BTABLE B,
     CTABLE C
WHERE A.A1 = B.B1
  AND A.A2 = B.B2
  AND A.A4 = C.C1
  AND C.TYPE = '1'
  AND C.RLST > ' '
  AND CAST (C.RLST AS FLOAT) > 10;

여기서 궁금한점은 WHERE 조건이 돌아가는 순서가 궁금합니다.

모든 컬럼들은 문자열입니다.

A.A3 = B.B3 을 조인을 일부러 뺐는데 제가 확인하는게 하나 있었는데 저 조인을 걸었을때는

CAST 부분에서 형변환 오류가 생겼습니다.

실제로 C.RLST 에 숫자가 아닌 다른값이 들어가 있어서 오류가 나는게 당연한데

A.A3 = B.B3 이걸 빼면 형변환 오류가 안생기고 A.A3 = B.B3 이걸 넣으면 형변환 오류가 생겼습니다..

이유가 궁금합니다

그리고 다른케이스로 CAST가 제일 마지막이 아닌 중간쯤에 있을때도 가끔 형변환 오류가 나기도 하던데

WHERE조건을 순차적으로 타서 그런걸까요??...

저 JOIN 하나를 빼도 나오는 각테이블 ROW는 모두 같다는 가정하에입니다..

 

 

 

by 마농 [2016.12.20 11:52:29]

1. 형변환 오류
  - C.RLST > ' ' 조건은 문자끼리의 비교이므로 형변환 오류 대상이 아닙니다.
  - 형변환 오류는 (CAST C.VALU AS FLOAT) > 10 이부분에서 나는 것입니다.
2. 처리 순서
  - 검색 범위를 줄여주는 조건이 있는 C 를 먼저 읽게 됩니다.
  - C > A > B 순서가 될 것이구요.
3. 부분범위 처리
  - 부분범위 처리를 지원하는 툴을 사용한다면?
  - 전체 결과가 아닌 일부 결과만 조회가 됩니다.
  - 페이지 처리라고 하고요. 툴에서 지원하는 것이죠.
  - 툴 말고 처리동작 자체도 부분범위 처리가 있습니다.
  - 대표적으로 NL(Nested Loop) 조인은 부분범위 처리가 됩니다.
4. 검색 조건 유뮤에 따른 결과 차이
  - 툴에서의 페이징 단위가 50 이라 가정하고
  - C 에서의 오류 데이터가 50 번째 존재한다고 가정했을 때
  - 조건절이 누락되면 카티션 곱이 발생하여 실제보다 더 많은 데이터가 조회됩니다.
  - 즉, 오류데이터까지 도달하지 못한 상태에서 50개의 운반단위를 채우는 거죠.
  - 그래서 첫번째 페이지에서는 에러가 안나는 거구요
  - 페이지(스크롤)을 내리면 결국 에러를 만나게 될 것입니다.
5. 그런데 조건절이 누락되어도 조회결과가 같다고 가정하셨네요?
  - 그럴리가 있을까? 하는 의심이 들구요.
  - 혹시 그 말이 맞다면? 실행계획의 변화를 생각할 수 있습니다.
  - 하지만 위 간단한 예시에서는 실행계획이 변할 것 같지는 않네요.


by alues [2016.12.20 12:00:51]

좋은 답변 감사합니다.

좀더공부를 해봐야겠네요.


by 아발란체 [2016.12.20 14:02:51]

아직도 배울게 많네용.. OTL 감사합니다.


by 마농 [2016.12.20 16:15:47]

아... 질문의 쿼리가 바뀌었네요.
처음 질문 봤을 때는 두개의 조건이 다른 컬럼 이었었는데...
두개의 조건이 동일 컬럼에 적용이 되고 있네요.
컬럼명 하나 때문에 전혀 다른 질문이 되어 버렸네요.
   - 1번.  AND C.RLST > ' '
   - 2번.  AND CAST (C.RLST AS FLOAT) > 10;
이 경우 보통 아래쪽 조건이 먼저 처리되는 것 같습니다.(확실치 않음)
   RLST 항목에 공백(' ')이 저장되어 있고..
   공백를 제외한 자료중 10보타 큰 자료를 찾는거라고 할 때
  1번이 먼저 처리 된후 2번이 처리된다면? 에러가 안나지만
  2번이 먼저 처리 된다면? 공백 때문에 에러가 발생합니다.
이를 해결하기 위해서는 조건절의 순서를 바꾸면 될까요?
   1번 조건을 아래쪽으로 내리면 될까요?
   1번이 먼저 수행될지 2번이 먼저 수행될지는 내부 로직이므로 장담 못합니다.
   DBMS 버전이 바뀌어 처리 로직이 달라진다거나 할 수 있죠.
공백을 제거하는 방향으로 가야 할 것 같습니다.
   AND TRIM(C.RLST) > 10


by 마농 [2016.12.20 16:28:23]
-- 테스트(11g) --
WITH c AS
(
SELECT /*+ materialize */ *
  FROM (SELECT '20' rlst FROM dual
        UNION ALL SELECT ' ' FROM dual
        )
)
SELECT *
  FROM c
 WHERE rlst > ' ' AND rlst > 10    --> 정상
-- WHERE rlst > 10 AND rlst > ' '    --> 오류
-- WHERE TRIM(rlst) > 10             --> 추천
;

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입