2. Altibase SQL 기본#
이 장에서는 Altibase의 SQL을 사용하기 위한 기본적인 사항들을 설명한다.
주석#
Altibase에서는 SQL문의 임의의 위치에 다음 두 가지 형식의 주석을 사용할 수 있다.
- /* */
C언어의 주석 형식과 동일한 방식으로 주석의 시작에 '/*'를 명시하고 주석의 끝에 '*/'를 명시한다. 여러 줄의 주석을 쓸 때 사용한다. - --
한 줄의 주석을 쓸 때 '-'를 연이어 두 번 명시하여 사용한다.
Altibase 객체 (Object)#
Altibase에서 제공하는 데이터베이스 객체(object)는 스키마가 객체와 비스키마 객체로 구분되며, 그 종류는 다음과 같다.
스키마 객체#
- 제약조건 (constraint)
- 인덱스 (index)
- 시퀀스 (sequence)
- 시노님 (synonym)
- 테이블 (table)
- 저장 프로시저 (stored procedure)
- 뷰 (view)
- 트리거 (trigger)
- 데이터베이스 링크(database link)
비 스키마 객체#
- 사용자 (user)
- 이중화 (replication)
- 테이블스페이스 (tablespace)
- 디렉토리 (directory)
객체 이름 규칙#
객체 이름#
데이터베이스 객체 이름에는 다음의 규칙이 적용된다.
-
객체의 이름의 최대 길이는 40바이트이다.
-
SQL문에서 객체의 이름을 쓸 때 인용부호는 사용해도 되고 사용하지 않아도 된다. 인용부호로 큰따옴표(")를 사용한다. 객체 생성시 따옴표로 묶어서 이름을 지정하면, 이 후에 그 객체를 참조할 때는 항상 큰따옴표로 묶은 이름을 사용해야 한다.
-
인용부호가 없는 이름은 대소문자가 구별되지 않는다. Altibase는 내부적으로 인용부호가 없는 이름을 대문자로 변경하며, 인용부호로 묶은 이름은 대소문자가 구별된다. 아래의 이름은 Altibase 내에서 같은 이름으로 사용되기 때문에 같은 이름 공간(Name Space)에서 다른 객체로 사용될 수 없다.
employees, EMPLOYEES, "EMPLOYEES"
-
인용부호가 없는 이름은 아래의 문자를 포함할 수 있다.
A-Z, a-z, 0-9, _, $, #
-
객체 이름의 첫 글자는 문자이거나 _ 이어야 한다. 그러나 아래의 문자로는 시작할 수 없다.
V$, X$ D$
-
인용부호가 있는 이름은 문자, 구두점 또는 공백을 포함할 수 있다. 그러나 큰따옴표(")를 포함할 수 없다.
-
Altibase의 예약어는 객체 이름으로 사용될 수 없다. (Altibase의 예약어 목록은 아래에 나열해 두었다.)
-
같은 이름공간(Name Space)내에는 같은 이름의 객체가 존재할 수 없다.
- 다음의 스키마 객체들은 한 이름공간을 공유한다:
- 테이블
- 뷰
- 시퀀스
- 시노님
- 저장 프로시저
- 다음의 스키마 객체들은 자신의 이름공간을 따로 소유한다:
- 제약조건
- 인덱스
- 트리거
- 데이터베이스 링크 객체
- 테이블과 뷰는 동일한 이름 공간를 공유하므로 동일한 스키마 내에 같은 이름의 테이블과 뷰는 존재할 수 없다. 그러나 테이블과 인덱스는 서로 다른 이름공간에 존재하기 때문에 동일한 스키마 내에 같은 이름의 테이블과 인덱스가 존재할 수 있다.
- 사용자, 이중화 객체, 테이블스페이스, 디렉터리 객체 같은 비스키마 객체들은 자신의 이름공간을 소유한다.
- 다음의 스키마 객체들은 한 이름공간을 공유한다:
Altibase가 제공하는 객체에 대한 자세한 설명은 Administrator's Manual을 참고하기 바란다.
비밀번호#
사용자가 Altibase에 접속하기 위해 사용하는 비밀번호 역시 객체 이름과 유사한 제약조건을 가진다. 암호에 사용가능한 문자는 A-Z, a-z, 0-9, _, $ 이다. 또한 Altibase의 예약어는 비밀번호에 사용될 수 없다. 첫 글자는 반드시 문자 또는 _여야 한다. 비밀번호의 최대 길이는 40바이트이다.
Altibase는 기본적으로 사용자 암호를 대소문자 구분 없이 대문자로 인식하여 다룬다. 사용자 암호의 대소문자를 구분하기 위해서는 CASE_SENSITIVE_PASSWORD 프로퍼티를 1로 설정한 다음, CREATE USER 구문으로 사용자를 생성할 때 암호를 큰따옴표(")로 묶는다. 만약 큰따옴표를 쓰지 않고, 암호를 지정하면 CASE_SENSITIVE_PASSWORD 프로퍼티가 1이더라도, 데이터베이스에서 암호를 대문자로 인식한다.
예약어#
다음 단어들은 Altibase에 예약되어 있는 단어들로 데이터베이스 객체 이름이나 비밀번호로 사용할 수 없다. 키워드 오른쪽의 (O)는 해당 키워드가 객체 이름으로는 사용될 수 없지만 테이블의 칼럼 이름으로는 허용됨을 표시한다. 데이터베이스 객체 생성시 또는 SQL구문 작성시에 이를 유념해야 한다. V$RESERVED_WORDS 성능뷰로 예약어를 확인할 수 있다.
_PROWID |
FIFO(O) |
PRIMARY |
ACCESS(O) |
FIXED(O) |
PRIOR |
ADD |
FLASHBACK(O) |
PROCEDURE |
AFTER(O) |
FLUSH(O) |
PURGE |
AGER(O) |
FLUSHER(O) |
QUEUE |
ALL |
FOLLOWING(O) |
RAISE |
ALTER |
FOR |
READ |
AND |
FOREIGN |
REBUILD |
ANY |
FROM |
RECOVER |
APPLY |
FULL(O) |
REMOVE |
ARCHIVE(O) |
FUNCTION(O) |
RENAME |
ARCHIVELOG(O) |
GOTO(O) |
REPLACE |
AS |
GRANT |
RETURN |
ASC |
GROUP |
RETURNING |
AT(O) |
HAVING |
REVOKE |
AUDIT(O) |
IF(O) |
RIGHT |
AUTOEXTEND(O) |
IN |
ROLLBACK |
BACKUP(O) |
INDEX |
ROLLUP |
BEFORE(O) |
INITRANS(O) |
ROW |
BEGIN(O) |
INNER(O) |
ROWCOUNT |
BETWEEN |
INSERT |
ROWNUM |
BODY(O) |
INSTEAD |
ROWTYPE |
BULK |
INTERSECT |
SAVEPOINT |
BY |
INTO |
SEGMENT |
CASCADE(O) |
IS |
SELECT |
CASE |
ISOLATION(O) |
SEQUENCE |
CAST(O) |
JOIN(O) |
SESSION |
CHECKPOINT(O) |
KEY(O) |
SET |
CLOSE(O) |
LANGUAGE(O) |
SHARD |
COALESCE(O) |
LATERAL |
SOME |
COLUMN |
LEFT(O) |
SPLIT |
COMMENT(O) |
LESS(O) |
SQLCODE |
COMMIT(O) |
LEVEL |
SQLERRM |
COMPILE(O) |
LIBRARY(O) |
START |
COMPRESS |
LIFO(O) |
STEP |
COMPRESSED(O) |
LIKE |
STORAGE |
CONJOIN(O) |
LIMIT(O) |
STORE |
CONNECT |
LINK |
SYNONYM |
CONSTANT |
LINKER |
TABLE |
CONSTRAINTS(O) |
LOB |
THAN |
CONTINUE(O) |
LOCAL |
THEN |
CREATE |
LOCK |
TIMESTAMPADD |
CROSS |
LOGANCHOR |
TO |
CUBE(O) |
LOGGING |
TOP |
CURSOR(O) |
LOOP |
TRIGGER |
CYCLE(O) |
MAXROWS |
TRUE |
DATABASE(O) |
MAXTRANS |
TRUNCATE |
DECLARE(O) |
MERGE |
TYPE |
DECRYPT(O) |
MINUS |
TYPESET |
DEFAULT |
MODE |
UNION |
DELAUDIT(O) |
MODIFY |
UNIQUE |
DELETE |
MOVE |
UNLOCK |
DEQUEUE(O) |
MOVEMENT |
UNPIVOT |
DESC |
NEW |
UNTIL |
DETERMINISTIC(O) |
NOAUDIT |
UPDATE |
DIRECTORY(O) |
NOCOPY |
USING |
DISABLE(O) |
NOCYCLE |
VALUES |
DISASTER(O) |
NOLOGGING |
VARIABLE |
DISCONNECT(O) |
NOT |
VC2COLL |
DISJOIN(O) |
NULL |
VIEW |
DISTINCT |
NULLS |
VOLATILE |
DROP |
OF |
WAIT |
EACH(O) |
OFF |
WHEN |
ELSE |
OFFLINE |
WHENEVER |
ELSEIF(O) |
OLD |
WHERE |
ELSIF(O) |
ON |
WHILE |
ENABLE(O) |
ONLINE |
WITH |
END(O) |
OPEN |
WITHIN |
ENQUEUE(O) |
OR |
WORK |
ESCAPE(O) |
ORDER |
WRAPPED |
EXCEPTION |
OTHERS |
WRITE |
EXEC(O) |
OUT |
|
EXECUTE(O) |
OUTER |
|
EXISTS |
OVER |
|
EXIT(O) |
PACKAGE |
|
EXTENT(O) |
PARALLEL |
|
EXTENTSIZE(O) |
PARTITION |
|
FALSE |
PIVOT |
|
FETCH(O) |
PRECEDING |
[표 2-1] 예약어 목록
힌트 구문#
구문#
hints ::=
전제 조건#
힌트는 아래의 구문에 명시할 수 있다
- 단순 SELECT, UPDATE, DELETE, INSERT 구문
- 복잡한 구문에서 메인 쿼리 또는 서브쿼리
- 복합 구문(집합 연산자로 묶인)에서 첫 번째 쿼리
설명#
SELECT, UPDATE, DELETE, INSERT 키워드 다음에 힌트를 명시할 수 있다.
주석 구분자(/*) 다음의 플러스 기호(+)는 그 주석이 힌트임을 Altibase에 알려주는 역할을 한다. 플러스 기호(+)는 주석 구분자 바로 뒤에 공백 없이 위치해야 한다.
하나의 주석 내에 공백으로 분리하여 여러 힌트를 명시할 수 있다.
힌트에 문법 오류가 있어도 힌트는 무시되고 쿼리는 실행된다.
각각의 힌트에 대한 문법은 다음 절 힌트 목록을 참조한다.
SQL 튜닝을 위한 힌트 선택은 Performance Tuning Guide를 참조한다.
예제#
Direct-Path INSERT Hint#
<질의> T1테이블의 모든 데이터를 Direct-Path INSERT 방식으로 T2테이블에 입력한다.
INSERT /*+ APPEND */ INTO T2 SELECT * FROM T1;
Table Access Method Hints (full scan, index scan, index ascending order scan, index descending order scan, no index scan)#
다음은 사원들 중 모든 여사원의 번호, 이름, 직업을 검색하는 질의이다.
SELECT eno, e_firstname, e_lastname, emp_job FROM employees WHERE sex = 'F';
예를 들어 많은 수의 사원들이 있는 사원 테이블의 성별(SEX) 칼럼에 인덱스가 정의되어 있고, 이 칼럼의 값은 'M' 또는 'F'이다.
만약, 남자 직원과 여자 직원의 비율이 같다면 full scan으로 전체 테이블을 검색하는 것이 index scan으로 검색하는 것보다 더 빠를 것이다. 그러나, 만약 여자 직원의 비율이 남자 직원보다 상대적으로 적다면, index scan이 전체 테이블의 full scan 보다 빠를 것이다. 즉, 칼럼이 서로 다른 두 개의 값만을 가지고 있을 때, 쿼리 옵티마이저는 각 값의 행들이 50%씩 존재한다고 가정해서 비용 기반 접근 방식으로서 index scan 보다 전체 테이블의 full scan을 선택한다.
아래의 질의들에서 access 회수를 비교해 보면 각각 20과 4인 것을 알수 있다.
<질의> 성별이 여자인 직원의 사원 번호, 이름, 직업을 출력하라. (full scan 이용)
iSQL> SELECT /*+ FULL SCAN(employees) */ eno, e_firstname, e_lastname, emp_job
FROM employees
WHERE sex = 'F';
ENO E_FIRSTNAME E_LASTNAME EMP_JOB
------------------------------------------------
.
.
.
------------------------------------------------
PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 65, COST: 0.18 )
SCAN ( TABLE: EMPLOYEES, FULL SCAN, ACCESS: 20, COST: 0.14 )
------------------------------------------------
<질의> 성별이 여자인 직원의 사원 번호, 이름, 직업을 출력하라. (index 이용)
iSQL> CREATE INDEX gender_index ON employees(sex);
Create success.
iSQL> SELECT /*+ INDEX(employees, gender_INDEX) use gender_index because there are few female employees */ eno, e_firstname, e_lastname, emp_job
FROM employees
WHERE sex = 'F';
ENO E_FIRSTNAME E_LASTNAME EMP_JOB
------------------------------------------------
.
.
.
------------------------------------------------
PROJECT ( COLUMN_COUNT: 4, TUPLE_SIZE: 65 )
SCAN ( TABLE: EMPLOYEES, INDEX: GENDER_INDEX, ACCESS: 4, SELF_ID: 2 )
------------------------------------------------
<질의> 1사분기(1월에서 3월까지) 동안의 모든 주문에 대한 주문번호, 상품번호, 주문량을 출력하라 (index 이용). 각 월에 해당하는 주문 테이블의 이름이 orders_## 라고 가정한다.
create view orders as
select ono, order_date, eno, cno, gno, qty from orders_01
union all
select ono, order_date, eno, cno, gno, qty from orders_02
union all
select ono, order_date, eno, cno, gno, qty from orders_03;
create index order1_gno on orders_01(gno);
create index order2_gno on orders_02(gno);
create index order3_gno on orders_03(gno);
iSQL> select /*+ index( orders,
orders1_gno, orders2_gno,orders3_gno ) */
ONO, GNO, QTY
from orders;
ONO GNO QTY
-------------------------------------------------
.
.
.
------------------------------------------------
PROJECT ( COLUMN_COUNT: 3, TUPLE_SIZE: 24 )
VIEW ( ORDERS, ACCESS: 14, SELF_ID: 6 )
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48 )
VIEW ( ACCESS: 14, SELF_ID: 5 )
BAG-UNION
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48 )
SCAN ( TABLE: ORDERS_01, INDEX: ORDERS1_GNO, ACCESS: , SELF_ID: 0 )
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48 )
SCAN ( TABLE: ORDERS_02, INDEX: ORDERS2_GNO, ACCESS: 4, SELF_ID: 1 )
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48 )
SCAN ( TABLE: ORDERS_03, INDEX: ORDERS3_GNO, ACCESS: 7, SELF_ID: 4 )
------------------------------------------------
Join Order Hints (ordered, optimized)#
<질의> 주문된 상품을 담당하고 있는 직원의 사원번호, 이름과 해당 고객의 이름을 출력하라. (employees 테이블과 customers 테이블을 조인하고, 그 결과를 orders 테이블과 조인하기 위해 ORDERED 힌트를 사용하라.)
iSQL> SELECT /*+ ORDERED */ DISTINCT o.eno, e.e_lastname, c.c_lastname
FROM employees e, customers c, orders o
WHERE e.eno = o.eno AND o.cno = c.cno;
ENO E_LASTNAME C_LASTNAME
------------------------------------------------
.
.
.
------------------------------------------------
PROJECT ( COLUMN_COUNT: 3, TUPLE_SIZE: 48 )
DISTINCT ( ITEM_SIZE: 40, ITEM_COUNT: 21, BUCKET_COUNT: 1024, ACCESS: 21, SELF_ID: 4, REF_ID: 3 )
JOIN
JOIN
SCAN ( TABLE: EMPLOYEES E, FULL SCAN, ACCESS: 20, SELF_ID: 1 )
SCAN ( TABLE: CUSTOMERS C, FULL SCAN, ACCESS: 400, SELF_ID: 2 )
SCAN ( TABLE: ORDERS O, FULL SCAN, ACCESS: 12000, SELF_ID: 3 )
------------------------------------------------
<질의> 주문된 상품을 담당하고 있는 직원의 사원번호, 이름과 해당 고객의 이름을 출력하라. (FROM 절의 테이블들의 순서에 상관없이 옵티마이저에 의해서 테이블 조인 순서가 결정되도록 하라.)
iSQL> SELECT DISTINCT o.eno, e.e_lastname, c.c_lastname
FROM employees e, customers c, orders o
WHERE e.eno = o.eno AND o.cno = c.cno;
ENO E_LASTNAME C_LASTNAME
------------------------------------------------
.
.
.
------------------------------------------------
PROJECT ( COLUMN_COUNT: 3, TUPLE_SIZE: 48 )
DISTINCT ( ITEM_SIZE: 40, ITEM_COUNT: 21, BUCKET_COUNT: 1024, ACCESS: 21, SELF_ID: 4, REF_ID: 1 )
JOIN
JOIN
SCAN ( TABLE: CUSTOMERS C, FULL SCAN, ACCESS: 20, SELF_ID: 2 )
SCAN ( TABLE: ORDERS O, INDEX: ODR_IDX2, ACCESS: 30, SELF_ID: 3 )
SCAN ( TABLE: EMPLOYEES E, INDEX: __SYS_IDX_ID_366, ACCESS: 30, SELF_ID: 1 )
------------------------------------------------
Optimizer Mode Hints (rule, cost)#
iSQL> SELECT /*+ RULE */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
iSQL> SELECT /*+ COST */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
Normal Form Hints (cnf, dnf)#
iSQL> SELECT /*+ CNF */ * FROM t1 WHERE i1 = 1 OR i1 = 2;
iSQL> SELECT /*+ DNF */ * FROM t1 WHERE i1 = 1 OR i1 = 2;
Join Method Hints (nested loop, hash, sort, sort merge)#
iSQL> SELECT /*+ USE_NL (t1,t2) */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
iSQL> SELECT /*+ USE_HASH (t1,t2) */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
iSQL> SELECT /*+ USE_SORT (t1,t2) */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
iSQL> SELECT /*+ USE_MERGE (t1,t2) */ * FROM t1, t2 WHERE t1.i1 = t2.i1;
Hash Bucket Size Hints (hash bucket count, group bucket count, set bucket count)#
iSQL> SELECT /*+ HASH BUCKET COUNT (20) */ DISTINCT * FROM t1;
iSQL> SELECT * FROM t1 GROUP BY i1, i2;
iSQL> SELECT /*+ GROUP BUCKET COUNT (20) */ * FROM t1 GROUP BY i1, i2;
iSQL> SELECT * FROM t1 INTERSECT SELECT * FROM t2;
iSQL> SELECT /*+ SET BUCKET COUNT (20) */ * FROM t1 INTERSECT SELECT * FROM t2;
Push Predicate Hints#
<질의> 1사분기(1월에서 3월까지) 동안 발생한 주문 중에서 한번의 주문수량이 10000개이상인 고객의 명단과 상품번호을 구하라.(고객 테이블과 주문 테이블을 조인하기 위해 Push Predicate 힌트를 사용하라.)
iSQL> create view orders_t as
2 select ono, order_date, eno, cno, gno, qty from orders orders_01
3 union all
4 select ono, order_date, eno, cno, gno, qty from orders orders_02
5 union all
6 select ono, order_date, eno, cno, gno, qty from orders orders_03;
Create success.
iSQL> alter session set explain plan = only;
Alter success.
iSQL> alter session set trclog_detail_predicate =1;
Alter success.
iSQL> select /*+ PUSH_PRED(orders_t) */ c_lastname, gno
2 from customers, orders_t
3 where customers.cno = orders_t.cno
4 and orders_t.qty >= 10000;
C_LASTNAME GNO
-------------------------------------
.
.
.
-----------------------------------------------------------
PROJECT ( COLUMN_COUNT: 2, TUPLE_SIZE: 34, COST: 1.68 )
JOIN ( METHOD: NL, COST: 1.67 )
SCAN ( TABLE: SYS.CUSTOMERS, FULL SCAN, ACCESS: ??, COST: 0.23 )
VIEW ( SYS.ORDERS_T, ACCESS: ??, COST: 0.07 )
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48, COST: 0.04 )
VIEW ( ACCESS: ??, COST: 0.04 )
BAG-UNION
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48, COST: 0.01 )
SCAN ( TABLE: SYS.ORDERS ORDERS_01, INDEX: SYS.ODR_IDX2, RANGE SCAN, ACCESS: ??, COST: 0.01 )
[ VARIABLE KEY ]
OR
AND
CUSTOMERS.CNO = ORDERS_01.CNO
[ FILTER ]
ORDERS_01.QTY >= 10000
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48, COST: 0.01 )
SCAN ( TABLE: SYS.ORDERS ORDERS_02, INDEX: SYS.ODR_IDX2, RANGE SCAN, ACCESS: ??, COST: 0.01 )
[ VARIABLE KEY ]
OR
AND
CUSTOMERS.CNO = ORDERS_02.CNO
[ FILTER ]
ORDERS_02.QTY >= 10000
PROJECT ( COLUMN_COUNT: 6, TUPLE_SIZE: 48, COST: 0.01 )
SCAN ( TABLE: SYS.ORDERS ORDERS_03, INDEX: SYS.ODR_IDX2, RANGE SCAN, ACCESS: ??, COST: 0.01 )
[ VARIABLE KEY ]
OR
AND
CUSTOMERS.CNO = ORDERS_03.CNO
[ FILTER ]
ORDERS_03.QTY >= 10000
-----------------------------------------------------------
힌트 목록#
이 절은 힌트 사용법과 의미를 간략히 설명한다. 각 힌트가 쿼리 옵티마이저를 위해 처리하는 방식에 대한 설명은 Performance Tuning Guide의 3장 쿼리 옵티마이저를 참고한다.
힌트는 그 기능에 따라 아래와 같이 분류된다.
Altibase는 모든 힌트에 대해 운영 프로그램을 수정하지 않고 ALTIBASE 에만 적용되는 힌트를 제공한다. 기존 힌트에 'ALTI_' 접두사를 붙여 사용하며 두 개 이상의 키워드로 구성된 힌트일 경우 space 를 under bar 로 대체한 후 'ALTI_' 접두사를 붙여 사용한다.
APPEND#
Direct-Path INSERT가 수행되도록 지시하는 힌트이다. 이 힌트는 INSERT 구문에만 사용할 수 있다. Direct-Path INSERT는 데이터가 입력될 때 페이지의 빈 공간을 찾아 들어가는 대신 새로운 페이지를 만들어 데이터를 입력하는 방식이다. Direct-Path INSERT와 관련된 통계 정보는 V$DIRECT_PATH_INSERT 성능 뷰를 조회해서 확인할 수 있다.
CNF#
WHERE절의 조건문들을 Conjunctive Normal Form으로 정규화할 것을 지시하는 힌트이다.
COST#
비용 기반으로 최적화된 실행 계획을 생성하도록 지시하는 힌트이다.
DELAY#
쿼리의 프로퍼티와 상관없이 실행 계획의 그래프를 기준으로 hierarchy, sorting, windowing, grouping, set, distinction의 실행(execute)이 패치(fetch)에서 수행되도록 하는 지연 기능을 활성화한다.
DISTINCT_HASH#
해싱 방식으로 DISTINCT를 처리할 것을 지시하는 힌트이다.
DISTINCT_SORT#
정렬 방식으로 DISTINCT를 처리할 것을 지시하는 힌트이다.
DNF#
WHERE절의 조건문들을 Disjunctive Normal Form으로 정규화할 것을 지시하는 힌트이다.
EXEC_FAST#
EXECUTOR_FAST_SIMPLE_QUERY 프로퍼티가 비활성화된 상태에서 힌트가 명시되면, 단순한 SELECT, INSERT, UPDATE, DELETE 구문은 SIMPLE QUERY로 동작한다. SIMPLE QUERY가 적용된 경우 실행 계획에 출력된다.
FIRST_ROWS#
처음 n개의 행을 가장 효율적으로 반환할 수 있는 실행 계획을 생성하도록 지시하는 힌트이다.
FULL SCAN#
명시한 테이블에 대해 테이블 전체 스캔을 수행할 것을 지시하는 힌트이다.
GROUP BUCKET COUNT#
GROUP-AGGREGATION과 AGGREGATION 실행 노드의 해시 버킷 수를 지정하는 힌트이다.
GROUP_HASH#
해싱 방식으로 GROUP BY절을 처리할 것을 지시하는 힌트이다.
GROUP_SORT#
정렬 방식으로 GROUP BY절을 처리할 것을 지시하는 힌트이다.
HASH_AJ#
중첩된 부질의가 Hash Join을 사용하여 Anti Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있으며, 만약 부질의가 Semi Join으로 풀리거나, 풀 수 없는 경우에는 효과가 없다.
HASH BUCKET COUNT#
HASH와 DISTINCT 실행 노드의 해시 버킷 수를 지정하는 힌트이다.
HASH_SJ#
중첩된 부질의가 Hash Join을 사용하여 Semi Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있다. 만약 부질의가 Anti Join으로 풀리거나 풀리지 않는 경우에는 효과가 없다.
HIGH_PRECISION#
사칙 연산 및 mod 연산 시 오차 발생을 방지하기 위하여 사용하는 힌트이다.
이 힌트를 사용할 때 데이타 타입으로 float 타입을 사용하여 연산한다. float 타입으로 연산할 경우 real이나 double 데이터 타입보다 연산 성능이 떨어질 수 있지만, 38자리까지의 사칙 연산 및 mod 연산의 정밀도를 보장한다.
INDEX#
명시된 인덱스를 사용하여 해당 테이블에 대해서 인덱스 스캔을 수행하도록 지시하는 힌트이다.
INDEX ASC#
명시된 인덱스를 사용하여 해당 테이블에 대해서 인덱스 스캔을 수행하되, 오름 차순으로 탐색한다.
INDEX_ASC#
INDEX ASC힌트와 같은 동작을 한다.
INDEX DESC#
명시된 인덱스를 사용하여 해당 테이블에 대해서 인덱스 스캔을 수행하되, 내림 차순으로 탐색한다.
INDEX_DESC#
INDEX DESC와 같은 동작을 한다
INVERSE_JOIN#
중첩된 부질의가 Semi Join 또는 Anti Join을 하는 경우 Inverse Join1을 반드시 사용하도록 지시하는 힌트이며, 부질의 내에 명시해야 한다.
해당 힌트는 Semi Join 또는 Anti Join 방법을 지시하는 다른 힌트와 함께 사용할 수 있다. 예를 들어 HASH_SJ와 함께 사용하는 경우, Hash Join이면서 Inverse Join인 Inverse Hash 조인을 사용하도록 지시한다.
KEEP_PLAN#
KEEP_PLAN는 한 번 생성된 플랜이 참조하는 테이블의 통계 정보가 변경되더라도 플랜이 재생성되는 것을 방지하고 그대로 사용하도록 지시하는 힌트이다. KEEP_PLAN 힌트는 쿼리의 direct/execute 수행뿐 아니라 prepare/execute 수행시에도 사용 가능하다.
LEADING#
힌트에 사용된 테이블들을 먼저 조인되도록 한다. 두 개 이상의 LEADING 힌트를 사용한 경우에는 처음 LEADING 힌트만 효과가 있다. ORDERED 힌트와 함께 사용된 경우에는 ORDERED 힌트가 무시된다. 힌트에 사용된 테이블에 Lateral View를 명시한 경우에는 효과가 없다.
MERGE_AJ#
중첩된 부질의가 Merge Join을 사용하여 Anti Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있으며, 만약 부질의가 Semi Join으로 풀리거나, 풀 수 없는 경우에는 효과가 없다.
MERGE_SJ#
중첩된 부질의가 Merge Join을 사용하여 Semi Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있으며, 만약 부질의가 Anti Join으로 풀리거나, 풀 수 없는 경우에는 효과가 없다.
NL_AJ#
중첩된 부질의가 Nested Loop Join을 사용하여 Anti Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있으며, 만약 부질의가 Semi Join으로 풀리거나, 풀 수 없는 경우에는 효과가 없다.
NL_SJ#
중첩된 부질의가 Nested Loop Join을 사용하여 Semi Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있다. 만약 부질의가 Anti Join으로 풀리거나 풀리지 않는 경우에는 효과가 없다.
NO_DELAY#
쿼리의 프로퍼티와 상관없이 실행 계획의 그래프를 기준으로 hierarchy, sorting, windowing, grouping, set, distinction의 실행(execute)이 패치(fetch)에서 수행되도록 하는 지연 기능을 비활성화한다.
NO_EXEC_FAST#
EXECUTOR_FAST_SIMPLE_QUERY 프로퍼티가 활성화된 상태에서 힌트가 명시되면, 단순한 SELECT, INSERT, UPDATE, DELETE 구문이더라도 SIMPLE QUERY로 동작되지 않는다.
NO_EXPAND#
CNF힌트와 같은 동작을 한다.
NO INDEX#
명시된 인덱스를 사용해서 해당 테이블에 대한 인덱스 스캔을 수행하지 않도록 지시하는 힌트이다.
NO_INDEX#
NO INDEX힌트와 같은 동작을 한다.
NO_INVERSE_JOIN#
중첩 부질의가 Semi Join 또는 Anti Join을 하는 경우, Inverse Join이 아닌 One-pass Hash Join이나 Two-pass Hash join을 선택하여 사용하도록 지시하는 힌트이다. 부질의 내에 명시해야 한다.
해당 힌트는 Semi Join 또는 Anti Join 방법을 지시하는 다른 힌트와 함계 사용할 수 있다. 예를 들어 HASH_SJ와 함께 사용하는 경우, Hash Join이면서 One-Pass Hash Join과 Two-Pass Hash Join 중 하나를 사용하도록 지시한다.
NO_MERGE#
메인 쿼리와 인라인 뷰 쿼리를 하나의 쿼리로 병합하지 않도록 지시하는 힌트이다.
NO_PARALLEL#
NOPARALLEL 힌트와 같은 동작을 한다.
NO_PLAN_CACHE#
NO_PLAN_CACHE는 생성된 플랜을 플랜 캐시에 저장하지 않도록 지시하는 힌트이다.
NO_PUSH_SELECT_VIEW#
뷰 외부의 WHERE절의 조건을 뷰 내부로 이동하여 처리하지 않도록 지시하는 힌트이다.
NO_SERIAL_FILTER#
SERIAL_EXECUTE_MODE 프로퍼티가 활성화된 상태에서 힌트가 명시되면, Serial Execute Mode 로 동작되지 않는다.
NO_TRANSITIVE_PRED#
조건절 이행을 배제하는 힌트이다. 조건절 이행에 대해서는 "Performance Tuning Guide > 3장 쿼리 옵티마이저 > 쿼리 변환 > 조건절 이행"을 참고한다.
NO_UNNEST#
Subquery Unnesting을 하지 말 것을 지시하는 힌트이다.
NO_USE_HASH#
HASH를 제외한 힌트 중에 조인방법이 선택된다.
NO_USE_MERGE#
MERGE를 제외한 힌트 중에 조인방법이 선택된다.
NO_USE_NL#
NL를 제외한 힌트 중에 조인방법이 선택된다.
NO_USE_SORT#
SORT를 제외한 힌트 중에 조인방법이 선택된다
PARALLEL#
일반 테이블 또는 파티션드 테이블을 스캔할 때 병렬 질의를 설정할 수 있는 힌트이다.
- NOPARALLEL: 병렬로 처리하지 않는다.
- PARALLEL integer: integer에 명시된 개수만큼의 쓰레드가 병렬로 처리한다.
PLAN_CACHE_KEEP#
Plan을 victim 선정 과정에서 제외시켜 Plan Cache내에 유지하도록 지시하는 힌트이다. 해당 힌트는 hardprepare 과정에서 적용된다. 그래서 사용자가 해당 plan을 unkeep으로 전환했을 때 softprepare가 발생해도 다시 keep 상태로 전환되지 않는다.
ORDERED#
FROM절에 나열된 순서대로 조인하도록 지시하는 힌트이다.
PUSH_PRED#
메인 쿼리의 WHERE 절에서 뷰와 관련된 조인 조건절을 뷰 안으로 밀어넣도록 지시하는 힌트이다.
PUSH_SELECT_VIEW#
뷰 외부의 WHERE절의 조건을 뷰 내부로 이동하여 처리하도록 지시하는 힌트이다.
RESULT_CACHE#
중간 결과를 캐시하는 ResultCache를 사용하는 힌트이다.
RULE#
비용을 배제하고 규칙 기반으로 최적화된 실행 계획을 생성하도록 지시하는 힌트이다.
SET BUCKET COUNT#
SET-INTERSECT와 SET-DIFFERENCE 실행 노드의 해시 버킷 수를 지정하는 힌트이다.
SERIAL_FILTER#
SERIAL_EXECUTE_MODE 프로퍼티가 비활성화된 상태에서 힌트가 명시되면, Serial Execute Mode 로 동작한다.
SORT_AJ#
중첩된 부질의가 Sort Join을 사용하여 Anti Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있으며, 만약 부질의가 Semi Join으로 풀리거나, 풀 수 없는 경우에는 효과가 없다.
SORT_SJ#
중첩된 부질의가 Sort Join을 사용하여 Semi Join 하도록 지시하는 힌트이다. 해당 힌트는 부질의 내부에 정의해야 효과가 있다. 만약 부질의가 Anti Join으로 풀리거나 풀리지 않는 경우에는 효과가 없다.
TEMP_TBS_DISK#
질의 처리 중에 생성되는 모든 중간 결과를 디스크 임시 공간에 저장하도록 지시하는 힌트이다.
TEMP_TBS_MEMORY#
질의 처리 중에 생성되는 모든 중간 결과를 메모리 임시 공간에 저장하도록 지시하는 힌트이다.
TOP_RESULT_CACHE#
최종 결과를 캐시하는 Top Result Cache를 사용하는 힌트이다.
UNNEST#
Subquery Unnesting을 하도록 지시하는 힌트이다.
USE_ANTI#
Full outer join 쿼리에서 명시된 테이블에 대해 left outer join과 anti outer join을 수행하고 그 결과를 concatenation하도록 지시하는 힌트이다. 단, 조인되는 양쪽 칼럼에 인덱스가 모두 존재하는 경우에만 해당 힌트가 적용된다. ANTI-OUTER-JOIN 노드를 참고한다.
USE_CONCAT#
DNF 힌트와 같은 동작을 한다.
USE_FULL_NL#
Full nested loop 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_FULL_STORE_NL#
Full store nested loop 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_HASH#
Hash 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다. 단 hasing 술어가 하나도 없을 경우 Nested loop 조인이 사용된다.
USE_INDEX_NL#
Index nested loop 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_INVERSE_HASH#
inverse hash 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_MERGE#
Sort Merge 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다. 단 sorting 술어가 하나도 없을 경우 Nested loop 조인이 사용된다.
USE_NL#
Nested loop 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_ONE_PASS_HASH#
One-pass hash 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_ONE_PASS_SORT#
One-pass sort 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_SORT#
Sort 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다. 단 sorting 술어가 하나도 없을 경우 Nested loop 조인이 사용된다.
USE_TWO_PASS_HASH#
Two-pass hash 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
USE_TWO_PASS_SORT#
Two-pass sort 조인을 사용해서 명시된 테이블을 조인하도록 지시하는 힌트이다.
-
Inverse Join이란 Inverse Index Nested Loop, Inverse Hash, Inverse Sort를 통칭한다. Inverse Join에 대한 자세한 설명은 Performance Tuning Guide를 참조하기 바란다. ↩