특정한 경우 DBMS_XPLAN.DISPLAY_CURSOR 결과의 Predicate Information 항목에서 IN 조건이 INTERNAL_FUNCTION으로 표시될 수 있습니다.
테스트를 위해 아래와 같이 테이블을 생성하겠습니다.
-- 1
DROP TABLE t1 PURGE;
CREATE TABLE t1 (c1 NOT NULL, c2 NOT NULL, c3 NOT NULL, c4 NOT NULL, c5 NOT NULL) AS
SELECT ROWNUM, ROWNUM, ROWNUM, ROWNUM, ROWNUM FROM XMLTABLE ('1 to 1000000');
CREATE INDEX t1_x1 ON t1 (c3, c4, c5);
아래 쿼리는 Predicate Information 항목에서 IN 조건이 OR 조건으로 표시됩니다.
-- 2
SELECT * FROM t1 WHERE c1 IN (1, 2);
-------------------------------------------
| Id | Operation | Name | Starts |
-------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
|* 1 | TABLE ACCESS FULL| T1 | 1 |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("C1"=1 OR "C1"=2))
아래 쿼리는 IN 조건을 다른 조건과 함께 사용합니다. Predicate Information 항목에서 IN 조건이 INTERNAL_FUNCTION으로 표시됩니다.
-- 3
SELECT * FROM t1 WHERE c1 IN (1, 2) AND c2 = 1;
-------------------------------------------
| Id | Operation | Name | Starts |
-------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
|* 1 | TABLE ACCESS FULL| T1 | 1 |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("C2"=1 AND INTERNAL_FUNCTION("C1")))
V$SQL_PLAN 뷰의 filter_predicates 칼럼에도 동일한 값이 저장되어 있습니다.
-- 4
SELECT filter_predicates FROM v$sql_plan WHERE sql_id = 'g2c4brasj44rm' AND id = 1;
FILTER_PREDICATES
------------------------------------
("C2"=1 AND INTERNAL_FUNCTION("C1"))
1개의 행이 선택되었습니다.
아래와 같이 IN 조건의 좌변을 가공하면 Predicate Information 항목에서 IN 조건이 OR 조건으로 표시됩니다.
-- 5
SELECT * FROM t1 WHERE c1 + 0 IN (1, 2) AND c2 = 1;
-------------------------------------------
| Id | Operation | Name | Starts |
-------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
|* 1 | TABLE ACCESS FULL| T1 | 1 |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("C2"=1 AND ("C1"+0=1 OR "C1"+0=2)))
인덱스 액세스 조건은 IN 조건을 다른 조건과 함께 사용해도 OR 조건으로 표시됩니다.
-- 6
SELECT * FROM t1 WHERE c3 IN (1, 2) AND c4 = 1;
---------------------------------------------------------------
| Id | Operation | Name | Starts |
---------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
| 1 | INLIST ITERATOR | | 1 |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 2 |
|* 3 | INDEX RANGE SCAN | T1_X1 | 2 |
---------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access((("C3"=1 OR "C3"=2)) AND "C4"=1)
인덱스 필터 조건은 테이블 필터 조건과 마찬가지로 다른 조건과 함께 사용한 IN 조건이 INTERNAL_FUNCTION으로 표시됩니다. 결론적으로 좌변을 가공하지 않은 IN 조건을 다른 조건과 함께 필터 조건으로 사용하면 IN 조건이 INTERNAL_FUNCTION으로 표시된다는 것을 유추할 수 있습니다.
-- 7
SELECT * FROM t1 WHERE c3 <= 1 AND c4 = 1 AND c5 IN (1, 2);
--------------------------------------------------------------
| Id | Operation | Name | Starts |
--------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 1 |
|* 2 | INDEX RANGE SCAN | T1_X1 | 1 |
--------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("C4"=1 AND "C3"<=1)
filter(("C4"=1 AND INTERNAL_FUNCTION("C5")))
Tanel Poder는 이에 대한 원인은 아래와 같이 설명합니다.
So, as we’ve seen above, some predicates with complex AND/OR conditions chained together are displayed as INTERNAL_FUNCTION() by DBMS_XPLAN.DISPLAY_CURSOR and V$SQL_PLAN as they are unable to decode (unparse) the execution plan info fully.
참고로 DBMS_XPLAN.DISPLAY 결과의 Predicate Information 항목은 IN 조건을 OR 조건으로 표시합니다.
-- 8
EXPLAIN PLAN SET STATEMENT_ID = 'TEST' FOR SELECT * FROM t1 WHERE c1 IN (1, 2) AND c2 = 1;
------------------------------------------
| Id | Operation | Name | Rows |
------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
|* 1 | TABLE ACCESS FULL| T1 | 1 |
------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("C2"=1 AND ("C1"=1 OR "C1"=2))
PLAN_TABLE 테이블의 filter_predicates 칼럼에도 동일한 값이 저장되어 있습니다.
-- 9
SELECT filter_predicates FROM plan_table WHERE statement_id = 'TEST' AND id = 1;
FILTER_PREDICATES
-----------------------------
"C2"=1 AND ("C1"=1 OR "C1"=2)
1개의 행이 선택되었습니다.
관련 링크