SQL 'where' 절의 조건 실행 순서
나는 내 where 조항에 다음과 같은 조건이 있습니다.
WHERE
d.attribute3 = 'abcd*'
AND x.STATUS != 'P'
AND x.STATUS != 'J'
AND x.STATUS != 'X'
AND x.STATUS != 'S'
AND x.STATUS != 'D'
AND CURRENT_TIMESTAMP - 1 < x.CREATION_TIMESTAMP
다음 중 어떤 조건이 먼저 실행됩니까?오라클을 사용하고 있습니다.
실행 계획에서 이러한 세부 정보를 얻을 수 있습니까? (여기에 있는 데이터베이스에서 해당 작업을 수행할 권한이 없습니다. 그렇지 않았다면 시도했을 것입니다.)
실행 계획을 볼 수 있는 권한이 없다고 확신하십니까?AUTOTTRACE를 사용하는 것은 어떻습니까?
SQL> set autotrace on
SQL> select * from emp
2 join dept on dept.deptno = emp.deptno
3 where emp.ename like 'K%'
4 and dept.loc like 'l%'
5 /
no rows selected
Execution Plan
----------------------------------------------------------
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 62 | 4 (0)|
| 1 | NESTED LOOPS | | 1 | 62 | 4 (0)|
|* 2 | TABLE ACCESS FULL | EMP | 1 | 42 | 3 (0)|
|* 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)|
|* 4 | INDEX UNIQUE SCAN | SYS_C0042912 | 1 | | 0 (0)|
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
3 - filter("DEPT"."LOC" LIKE 'l%')
4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")
보다시피 쿼리가 실행되는 방법에 대한 자세한 정보를 제공합니다.이는 다음과 같습니다.
- "EMP.ename('K%'와 같은 이름)" 조건이 EMP의 전체 스캔에 먼저 적용됩니다.
- 그러면 일치하는 DEPT 레코드가 (NESTED LOOPs 방법을 통해) 뎁트.뎁트노의 인덱스를 통해 선택됩니다.
- 마지막으로 'l%'와 같은 필터 "dept.loc"이 적용됩니다.
이 응용 프로그램 순서는 이 재정렬된 쿼리를 통해 알 수 있듯이 WHERE 절에서 술어가 정렬되는 방식과는 아무런 관련이 없습니다.
SQL> select * from emp
2 join dept on dept.deptno = emp.deptno
3 where dept.loc like 'l%'
4 and emp.ename like 'K%';
no rows selected
Execution Plan
----------------------------------------------------------
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 62 | 4 (0)|
| 1 | NESTED LOOPS | | 1 | 62 | 4 (0)|
|* 2 | TABLE ACCESS FULL | EMP | 1 | 42 | 3 (0)|
|* 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)|
|* 4 | INDEX UNIQUE SCAN | SYS_C0042912 | 1 | | 0 (0)|
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("EMP"."ENAME" LIKE 'K%' AND "EMP"."DEPTNO" IS NOT NULL)
3 - filter("DEPT"."LOC" LIKE 'l%')
4 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")
데이터베이스는 조건을 실행할 순서를 결정합니다.
일반적으로 가능한 경우 인덱스를 먼저 사용합니다(항상 그렇지는 않습니다).
앞서 말한 것처럼 실행 계획을 보면 몇 가지 정보를 얻을 수 있습니다.그러나 계획 안정성 기능을 사용하지 않는 한 실행 계획이 항상 그대로 유지되어야 합니다.
올려주신 질의의 경우 평가 순서가 논리를 전혀 바꾸지 않을 것으로 보여 효율성을 생각하시는 것 같습니다.Oracle Optimizer는 효율적인 계획을 선택할 가능성이 높습니다.
성능을 기본 쿼리와 비교하려는 경우 특정 주문을 장려하기 위해 수행할 수 있는 방법이 있습니다.예를 들어 타임스탬프 조건을 먼저 실행하려고 했다고 가정합니다.다음과 같이 할 수 있습니다.
WITH subset AS
( SELECT /*+ materialize */
FROM my_table
WHERE CURRENT_TIMESTAMP - 1 < x.CREATION_TIMESTAMP
)
SELECT *
FROM subset
WHERE
d.attribute3 = 'abcd*'
AND x.STATUS != 'P'
AND x.STATUS != 'J'
AND x.STATUS != 'X'
AND x.STATUS != 'S'
AND x.STATUS != 'D'
"구체화" 힌트를 사용하면 최적화 도구가 먼저 인라인 쿼리를 실행한 다음 결과 집합에서 다른 조건을 검색할 수 있습니다.
저는 당신에게 이것을 일반적인 습관으로 하라고 충고하는 것이 아닙니다.대부분의 경우 단순 쿼리를 작성하는 것만으로도 최상의 실행 계획을 얻을 수 있습니다.
실행 계획에 대한 다른 의견을 덧붙이자면, 9i에서 도입되고 10g+에서 기본적으로 사용되는 CPU 기반 비용 모델 하에서 Oracle은 테이블 액세스 순서와 방법에 영향을 미치지 않더라도 어떤 서술어 평가 순서가 더 낮은 계산 비용을 초래하는지 평가할 것입니다.하나의 술어를 다른 술어보다 먼저 실행하면 술어 계산이 실행되는 횟수가 줄어들면 최적화를 적용할 수 있습니다.
자세한 내용은 다음 문서를 참조하십시오. http://www.oracle.com/technology/pub/articles/lewis_cbo.html
또한 Oracle은 체크 제약 조건 또는 파티션 정의와 비교하여 행이 반환되지 않는 경우에도 술어를 실행할 필요가 없습니다.
복잡한 것들.
마지막으로, 관계형 데이터베이스 이론에 따르면 쿼리 절의 실행 순서에 절대 의존할 수 없으므로 시도하지 않는 것이 좋습니다.다른 사람들이 말했듯이, 비용 기반 최적화 도구는 자신이 가장 좋다고 생각하는 것을 선택하려고 하지만, 설명 계획을 보는 것조차 실제 사용되는 주문을 보장하지는 않습니다.계획을 설명하면 CBO가 권장하는 것을 알 수 있지만, 여전히 100%는 아닙니다.
당신이 왜 이런 일을 하려고 하는지 설명한다면, 어떤 사람들은 계획을 제안할 수도 있을 것입니다.
까다로운 질문.같은 딜레마에 직면했을 뿐입니다.쿼리 내에서 함수를 언급해야 합니다.함수 자체가 다른 쿼리를 만들기 때문에 일반적으로 성능에 어떤 영향을 미치는지 이해할 수 있습니다.그러나 대부분의 경우 나머지 조건이 먼저 실행되면 기능이 자주 호출되지 않을 것입니다.
글쎄요, 여기에 다른 주제의 기사를 올리는 것이 유용할 것 같습니다.
다음 인용문은 Donald Burleson의 사이트(http://www.dba-oracle.com/t_where_clause.htm) 에서 복사한 것입니다.
ordered_predicates 힌트는 쿼리의 Oracle WHERE 절에 지정되며 부울 술어를 평가할 순서를 지정하는 데 사용됩니다.
ordered_predicates가 없는 경우 Oracle은 다음 단계를 사용하여 SQL 술어의 순서를 평가합니다.
하위 쿼리는 WHERE 절의 외부 부울 조건 전에 평가됩니다.
내장 함수나 하위 쿼리가 없는 모든 부울 조건은 WHERE 절에 있는 순서와 반대로 평가되며, 마지막 서술어가 먼저 평가됩니다.
각 술어의 내장 함수가 있는 부울 술어는 추정 평가 비용의 증가 순서로 평가됩니다.
언급URL : https://stackoverflow.com/questions/340139/execution-order-of-conditions-in-sql-where-clause
'it-source' 카테고리의 다른 글
ggplot을 사용하여 축의 숫자 형식을 변경하려면 어떻게 해야 합니까? (0) | 2023.06.20 |
---|---|
인증스프링 보안의 성공 담당자 (0) | 2023.06.20 |
VScode PHPCS 확장 오류: 참조된 Snip "WordPress-Core"가 없습니다. (0) | 2023.06.20 |
GitHub 프로젝트에서 특정 커밋을 얻는 방법 (0) | 2023.06.20 |
SQL: AVG(NULL 값 포함) (0) | 2023.06.20 |