3.3.8. 기타
APPEND
데이터를 입력하는 INSERT문에서 사용하는 힌트이다.
데이터 입력작업을 'DIRECT-PATH'방식으로 수행되도록 하여 SGA를 거치지 않고 직접 저장공간으로 입력이 되도록 함으로써 매우 빠른 입력처리를 보장한다.
한가지 유의할 점은 반드시 최고 수위점(High water mark)다음 위치에 데이터를 저장한다는 것이다.
예) INSERT /*+ APPEND */ INTO TAB2
SELECT *
FROM TAB1
WHERE COL1 >= '20050101';
CACHE
전체 테이블 스캔방식으로 읽혀진 블록을 데이터베이스의 버퍼캐쉬를 관리하는 LRU 리스트의 최근 사용위치 (Most Recent Used End)에 머물도록 하여 계속해서 메모리 내에 머물 수 있도록 하는 힌트이다
크키가 작은 테이블에 유용하게 사용될수 있다. 이 힌트를 사용하면 옵티마이져는 테이블에 이미 정의되었던 기본 캐쉬(Default Caching)정의를 무효화한다.
예) SELECT /*+ FULL(t) CACHE(t) */ last_name
FROM tech_spec t;
NOCAHCE
예) SELECT /*+ FULL(m) NOCACHE(m) */ member_name
FROM member m;
CARDINALITY
예) SELECT /*+ CARDINALITY( s 9999 ) */ ...
FROM sales s, prod p
WHERE s.sales_date >= '20050901'
AND p.prod_id LIKE 'ABEC%';
CURSOR_SHARING_EXACT
CURSOR_SHARING 초기화 파라메터가 'EXACT'로 지정되어 있다면 리터럴 값을 바인드 변수로 변경하지 않고 있는 그대로 파싱을 한다.
FORCE와 SIMILAR를 지정하면 SQL조건절에 상수값을 지정했다라도 옵티마이져는 변수로 인정하여 실행계획을 수립하므로 실행계획의 공유비율을 높일 수 있다.
또한 경우에 따라서 'ALTER SESSION …'명령을 이용하여 이 파라메터를 조정하기도 한다. 그러나 SQL에서 지정한 상수값에 따라 미묘하게 달라지는 실행계획을 얻을 수 없으므로 이 힌트를 이용하여 CURSOR_SHARING 파라메터를 'EXACT'로 지정한것과 동일한 상태로 만들수 있다.
예) SELECT /*+ CURSOR_SHARING_EXACT */ *
FROM EMP
WHERE ENAME = 'SCOTT';
DRIVING_SITE
예) SELECT /*+ DRIVING_SITE(b) */..........
FROM cust a, order@ord_svr b
WHERE a.join_date >= '20050101'
AND b.order_date >= TO_CHAR(SYSDATE-7,'YYYYMMDD');
DYNAMIC_SAMPLING
우리가 통계정보를 생성해두지 않았더라도 언제나 비용기준(CBO)으로 작동할수 있게 하기위한 동적 표본화(Dynamic sampling)에 관한 힌트이다.
이 기능은 통계정보를 가지고 있지않거나, 에러 등의 문제로 사용할수 없게 되거나, 너무 오래되어 더 이상 신뢰할수 없을 때 적용한다.
샘플링 레벨은 0~10 사이로 줄수 있으며, 값이 클수록 더욱 정확한 통계정보를 수집하게 된다. 이 힌트는 바로 이 기능을 단위 SQL에 적용할수 있기 위해 탄생되었다.
예) SELECT /*+ DYNAMIC_SAMPLING(e 1) */ .....
FROM EMP
WHERE ENAME = 'SCOTT';
예) SELECT /*+ DYNAMIC_SAMPLING(e 1) */ count(*)
FROM employees e;
PUSH_PRED
예) SELECT /* NO_MERGE(v) PUSH_PRED(v) */..........
FROM member m,
( SELECT carrier_name, carrier_duration
FROM member_carrier
WHERE carrier_type IN ('1','2','4') ) v
WHERE m.member_id = v.member_id(+)
AND m.member_type= '1001';
NO_PUSH_PRED
예) SELECT /* NO_MERGE(v) NO_PUSH_PRED(v) */..........
FROM employees e,
( SELECT manager_id
FROM employees) v
WHERE e.manager_id = v.manager_id(+)
AND e.employee_id = 100';
PUSH_SUBQ
이 힌트는 머지되지 않는 서브쿼리를 최대한 먼저 수행할 수 있도록 실행계획을 수립하기를 요구한다.
머지가 된 서브쿼리는 먼저 수행되고 그 결과를 메인쿼리의 처리범위를 줄이는 '제공자'역활을 한다. 그러나 일반적으로 머지가 불가능해지면 '확인자'역활을 해야 하기 때문에 실행계획의 마지막 단계에서 수행된다. 만약 머지를 할수 없는 서브쿼리가 상대적으로 적은 로우를 가지고 있거나 처리범위를 줄여 주는데 중요한 역활을 할 수 있다면 이 힌트를 이용하여 최대한 앞 부분에서 수행되도록 함으로써 수행속도 향상을 얻을 수 있다.
예를 들어 어떤 쿼리가 선택한 결합 인덱스에서 중간에 있는 컬럼에 조건이 부여되지 않았을때 '='조건을 공급하기 위해서 서브쿼리를 추가 했는데 우리의 생각과는 달리 서브쿼리가 확인자의 역활을 하도록 실행계획이 수립된다면 이 힌트를 이용하여 제공자 역활을 하도록 할수 있다.
예) SELECT /*+ PUSH_SUBQ(@qb) */.......... [INDEX: ITEM+SALTYPE+SALDATE]
FROM sales
WHERE item = :b1
AND saltype IN (SELECT /*+ QB_NAME(qb) */ code_id
FROM code_table
WHERE code_type = 'SALTYPE' )
AND saldate between :b2 and :b3;
QB_NAME
쿼리 블록에 이름을 부여하여 해당 쿼리 블록 외부의 다른 힌트에서 지정한 쿼리블록을 참조할 수 있도록 하는 힌트이다.
Query Block에 명시적으로 이름을 부여하는 역할을 한다. 주로 Inline View나 Subquery 등에 이름을 붙여서 실행 계획의 가독성을 높이는 용도로 사용된다.
명명하지 않은 쿼리 블록의 경우 옵티마이져가 자동으로 부여(PLAN_TABLE에서 확인)
-
예) SELECT /*+ UNNEST(@qb) */........
FROM emp e
WHERE e.deptno IN (SELECT /*+ QB_NAME(qb) */ d.deptno
FROM dept d
WHERE d.loc = 'DALLAS');
REWRITE_OR_ERROR
예) SELECT /*+ REWRITE_ OR_ERROR */ p.prod_subcatgory,
SUM(s.amount_sold)
FROM sales s, products p
WHERE s.prod_id = p.prod_id
GROUP BY p.prod_subcatgory;
ORA-30393: a query block in the statement did not rewrite
참조한문서