티스토리 뷰

공부/SQL

오라클_SQL_힌트

감성윤 2016. 4. 28. 17:16

1. 스캔의 기본 유형

  * 전체테이블 스캔 (Full Table Scan)

  * 로우식별자 스캔 (Rowid Scan)

  * 인덱스 스캔 (Index Scan)

  * 클러스터 인덱스(Cluster Index)

  * 해쉬 액세스(Hash Access)

  * 표본 테이블 스캔(Sample Table Scan)


 1.1 전체테이블 스캔 (Full Table Scan)

   : 테이블에 있는 모든 로우들을 읽음. 최고 수위선(High Water Mark) 내에 있는 모든 블록 들을 스캔.

    

   - 만약 기존에 존재하던 많은 데이터들이 삭제되어서 대부분의 블록이 비어 있더라도 최고 수위선이 수정되어 있지 않으면 불필요한 스캔 발생

   - 한번에 액세스하는 블록의 양을 정의하려면 DB_FILE_MULTIBLOCK_READ_COUNT 초기화 파라미터에서 지정

   - 대용량 테이블의 경우 유리. 인덱스 스캔과 비교해서 자료 분포도상 손익 분기점을 찾는게 중요.

   

   1.1.1 옵티마이저가 선택하게 되는 경우

    ① 적용가능 인덱스의 부재

    ② 넓은 범위의 데이터 액세스

    ③ 소량의 테이블 액세스

    ④ 병렬처리 액세스

    ⑤ FULL 힌트 적용시



 1.2 로우식별자 스캔 (Rowid Scan)

   : 단 하나의 로우를 테이블에서 추출하는 가장 빠른 방법

   

   - ROWID 값을 리터럴 값으로 직접 사용하지 말고 바인드변수로 사용할것 : 로우의 이주, 체인 발생, IMP/EXP 시에도 변경이 됨

   - ROWID 스캔은 인덱스를 사용할때 발생하지만 모든 인덱스 스캔에서 발생하는 것은 아님


  1.3 인덱스 스캔 (Index Scan)

   - 인덱스를 경유하여 로우를 추출할때도 결국 I/O는 블록 단위로 발생

   - 찾고자 하는 로우들이 몇개의 블록 내에 잘 모여 있다면 훨씬 적은 블록을 액세스 할 수 있음 (운송단가:클러스터링 팩터)

   

   1.3.1 인덱스 유일 스캔(Index Unique Scan)

    : 단 하나의 Rowid를 추출

    

    - 대부분의 경우 옵티마이저에서 제대로 판단

    - 강제로 힌트 적용시에도 수행할 수 없는 형태의 쿼리라면 옵티마이저에서 무시한다.

    - 힌트 : INDEX(table_alias  index_name) 적용

    -  데이터베이스 링크를 사용했을때 유일 인덱스가 사용가능한데 옵티마이저가 판단하지 못했다면 힌트를 부여할 수 있다.


   1.3.2 인덱스 범위 스캔(Index Range Scan)

    : 가장 보편적인 데이터 액세스 유형


    - 하나이상의 인덱스 선행컬럼에 조건이 부여되어야 함

    - 힌트는 인덱스 유일스캔과 동일


   1.3.3 인덱스 역순 범위 스캔(Index Range Scan Descending)

    : 역순으로 데이터를 액세스 한다는 것을 제외하면 인덱스 스캔과 동일


    - 쿼리에서 'order by ... desc'를 할때 옵티마이저의 판단에 따라 일어남

    - 힌트 : INDEX_DESC(table_alias  index_name)


   1.3.4 인덱스 스킵 스캔 (Index Skip Scan)

    : 결합 인덱스 선행 컬럼 생략시에 인덱스 스캔을 할 수 없었던 문제와 중간에 위치한 일부 컬럼 생략시 많은 양의 인덱스 스캔이 발생하던 현상을 해결하기 위해 도입된 방식


    - 인덱스를 사용하지 못할때라면 모르겠지만 제대로 된 인덱스가 존재할때는 불리

    - 힌트 : INDEX_SS, INDEX_SS_ACS, INDEX_SS_DESC(table_alias  index_name)


   1.3.5 인덱스 전체 스캔(Index Full Scan)

    :조건절에 인덱스의 컬럼이 적어도 하나 이상 사용되었을때 적용이 가능


    - 다음의 두가지 경우를 만족할때는 조건절에 사용된 컬럼이 없어도 적용가능

     ⓐ 쿼리 내에 사용된 어떤 테이블들의 모든 컬럼들이 그 인덱스에 모두 존재

     ⓑ 인덱스 컬럼 중에서 최소한 NOT NULL인 컬럼이 하나는 존재할 때


    - 만약 NOT NULL 컬럼이 하나도 없다면 최악의 경우 어떤 인덱스 로우는 모두 null 값이 되므로 인덱스에 저장되지 않을 수 있기 때문에

      전체 테이블 row 수와 달라지므로 테이블을 대신 할 수 없다.

    - 힌트 : 


   1.3.5 인덱스 고속 전체 스캔 (Index Fast Full Scan)

    : Table Full Sacn의 대안으로 사용, 인덱스 전체 스캔과 다른 점은 마치 테이블 액세스처럼 한 번의 I/O에 다중 블록을 액세스 한다는 것


    - 병렬처리를 사용할 수 있기 때문에 인덱스 전체 스캔이나 테이블 전체 스캔에 비해 빠르다.

    - 비트맵 인덱스에서는 적용 불가

    - 힌트 : INDEX_FFS(table_alias  index_name),     NO_INDEX_FFS(table_alias  index_name) - 강제해제




2. 데이터 연결을 위한 실행 계획

 * 내포 조인(Nested Loops Join)

 * 정렬 병합(Sort Merge Join)

 * 내포 조인(Hash Join)


 2.1 내포 조인(Nested Loops Join)

  : 가장 고전적, 범용적 조인. 어떤 범위의 집합의 각 로우에 대하여 연결고리를 통해 반복적으로 다른 집합에 대응대는 로우를 탐침


  - 먼저 수행되는 집합의 처리범위가 전체의 일량을 좌우

  - 나중에 반복 수행되는 연결 작업이 랜덤 액세스로 발생

  - 소량의 범위를 연결할 때는 매우 유용하지만 대량 범위는 커다란 부하

  - 힌트 : USE_NL(table1, table2). 해당 힌트와 함께 스캔방식을 적용하고 싶다면 다른 힌트를 같이 기술할 수 있다.


  2.1.1 수행 순서

   ① 먼저 수행될 외측 집합을 결정한다. 이것을 선행(Driving)집합이라 부른다.

   ② 선행 집합이 액세스 되면 그들의 모든 컬럼은 상수값을 가진다.

   ③ 이 방법으로 조인될 집합이 더 있다면 위의 방법으로 나머지 순서도 결정

   ④ 실제로 조인이 수행될 때는 외측 집합 각각의 로우에 대해 내측 집합의 대응되는 모든 로우가 액세스된다.


   참고) plan 상에서 Nested Loops 가 실행될때의 구조

      Nested Loops

        outer_loop

        inner_loop


 2.2 정렬 병합 조인(Sort Merge Join)

  : Nested Loops 조인이 가진 문제를 해결하기 위한 대안.

    조인의 대상 범위가 넓을 때 발생하는 랜덤 액세스를 줄이기 위한 경우나 연결고리에 마땅한 인덱스가 존재하지 않을때 사용

   

   - 랜덤 액세스를 하지 않고 스캔을 하면서 조인을 수행한다.

   - 반드시 먼저 2개의 집합이 연결을 할 수 있는 구조로 정렬되어야 한다.

      (연결은 효과적으로 수행하게 되지만 먼저 정렬을 해야 한다는 부담이 있음)

   - 정렬을 메모리에서 수행되기 때문에 정렬을 위한 영역(Sort Area Size)에 따라 효율의 차이가 크다.

   - 정렬이 된 집합이 준비되어 있거나 인덱스를 활용하여 정렬을 대신할 수 있다면 이 조인이 유리.(그 외에는 해쉬조인이 유리)

   - 연결 고리의 비교 연산자가 '='이 아닐때 Nested Loops 조인보다 유리한 경우가 많다.

   - 선행집합 이라는 개념이 없다.

   - 연결을 위한 준비작업은 연결 고리 컬럼값으로 정렬된다.

   - 양쪽 집합은 스캔 방식으로 통해 연결을 시도. 설사 인덱스가 존재하더라도 연결을 위해서는 결코 사용되지 않는다.

      (각각의 집합내에서의 정렬에서는 인덱스가 사용됨. 구분할 것)

   - 힌트 : USE_MERGE(table1, table2)


 2.3 해쉬 조인(Hash Join)

  : 해슁함수 기법을 활용하여 조인을 수행. 컬럼의 값을 받아서 이 함수를 경유하면 로우의 저장위치를 리턴하는 것으로

  이를 활용한 것이 해쉬클러스터이다.


  - 부하 부담이 많은 랜덤 액세스가 발생하지 않으면서 정렬의 부담을 해결 할 수 있는 방법을 가져야 한다.

  - 해슁함수는 직접적인 연결을 담당하는 것이 아니라 연결될 대상을 특정 지역에 모아두는 역할만을 담당한다.

  - 파티션(Partition) : 동일한 해쉬값을 가진 데이터들을 모아두는 공간

  - 파티션짝(Pair) : 서로 조인해야 할 것들을 연결하는것

  - 연결 작업을 위해 작은 파티션을 메모리 내에 임시적인 해쉬테이블로 만든다. 큰 파티션의 로우들이 외측 루프가 되고 해쉬

    테이블 액세스는 내측 루프가 되어서 조인을 수행한다.

  - 동치조인(Equijoin) 일때만 가능

  - 대량 범위에 대한 조인이나 데이터들이 너무 많은 조각으로 산재되어 있을 때 특히 유리

  - 힌트 : USE_HASH(table1, table2)


  - 드라이빙  쪽의 처리범위가 넓어 처리량이 매우 많은 경우

  - 랜덤액세스가 많은 경우

  - 대상건수가 많고 두 집합간의 크기 차이가 심한 경우

  - 연결고리 이상이 생겨 비이상적인 실행계획 또는 Range Scan이 일어날 경우


  ------------------------------------------------------------------------------------------------

   Technical Bulletins 의 내용



   Explanation

   -----------

   (1) 개요 

   JOIN 의 종류는 3가지로 나뉘는데, Sort merge join, Nested loop join, Hash join 이다.

    이중 Hash Join (HJ) 은  7.3 부터 사용가능하며 그 주요 기능을 살펴보면 


    - index 가 여러 level 의 depth 를 가질 때  Sort Merge Join (SMJ) 이나  

      Nested   Loops (NL)보다 좋은 효과를 낸다. 


    - sort 를 하지 않으므로 SMJ 보다 좋은 성능을 내며, 작은 table 과 큰  

      table 의 join 시에 유리하다. 


    - 주의해야 할 것은 hash  join 은 equi join 에서만 가능하다는 것이다.


    - HJ 은 driving table 에 index 를 필요로 하지 않는다.


    - SMJ 나 NL 보다 효율적인데, 이는 SMJ 가 merge 단계에 들어가기 위해 

     양쪽 table 이 모두 sort 되어야 하기 때문이다. 또 NL은 driving table

     이 많은 row 의 data 를 갖는 경우 비효율적이서 inner table 을 여러번 

     probe(탐색)하게 한다. 이에 반해 HJ는 각 table 에 대해 1 번만 pass 한

     다. 



   (2) Cost의 비교 

   편의상 join 되는 sql 문이 다음과 같다고 가정하자.


   SELECT S.a, B.a FROM S,B WHERE S.a = B.a

   S는 small table 이고, B는 big table 이다.


   (* analyze 를 수행하면 CBO 는 이미 S가 out table 이고 B 가 inner table 

    이며 , S 가 driving table 임을 인식한다. )


   NLJ 는 S table 의 모든 row 에 대해 a column 을 B table 의 모든 column 을

   match 하기 때문에  rS* rB key 비교가 요구된다.:

    

   Cost(NLJ) 는 Read(S) + [ rS *Read(B) ] 에 비례


   또 SMJ 는 S 와 B 를 memory 에 읽어와 join key 를 각각 sort 하고, join 을

   수행하므로 cost 는 


   Cost(SMJ) 는 Read(S) + Write(SortRuns(S)) 


        + Read(B) + Write(SortRuns(B)) 


        + Merge(S,B) 


        + CPUSortCost(S + B) 에 비례한다.


   memory 에서 수행되는 HJ 의  algorithm 은 아래에서 설명된어 지는데 이의

   cost 를 미리 check 해 보자면 

    

   Cost(HJ) = Read(S) + Build Hash Table in Memory (cpu) 


        + Read(B) + Perform In memory Join(cpu)


   이 경우 CPU costs를 무시하면 ,  


   Cost(HJ)는 Read(S) + Read(B) 에 비례한다고 할수 있다.



   (3) Hash join 을 수행하기 위해 Oracle 은 다음의 과정을 거친다.: 

   이를 수행하기 위해 partition 단계와 join 단계를 거치며 이의 algorithm 을 

   grace join 이라 한다. 

   이의 한계는 join value 의 분배가 한쪽으로 치우침이 없이 

   partition 에 고르게 분포되어야 한다는 것이다.


   이 algorithm 은 다음과 같다.


   1. partiton 갯수를 결정한다.이를 fan out 이라한다.

      high fan out 은 여러개의 작은 partition 을 만들어 i/o 의 효율을 떨어

      뜨리며,low fan out 은 커다란 partition 을 만들어 hash memory 의 hit 

      율을 떨어뜨린다 . 그러므로 이를 적절히 가져가는 것이 performance 의 

      주 요점이며(이는 bit map 갯수를 결정) 이의 효율을 높이기 위해 hash 

      area size를 늘리고, hash multi block io 를 줄인다.

      

   2. driving table 을 결정한다.(작은 table 로 결정)


   3. small table 의 필요 column 을 읽어들여 hash area 의 partition 에 분배

      하는데 이는 join column 으로 hash function1을 통과 시키면서 

      partition 에 hash function2 의 hash value 와 함께 분배한다.

      이때 bitmap vector 를 만든다. 

      이 bitmap 은 2차원 bucket 인데 hash function 1 과 2 를 통과시켜 만든 

      다.즉 partition 이 100 개라면 100* 100 의 10000 개의 cell 로 이루어

      진다.


   4. 각 row 에 대해 bitmap 의 (a,b) 에 marking 을 한다.


   5  위의 step 이 모두 끝나면 driving table 이 아닌 큰 table 을 읽어들여

      function1,2 를 통과한다.

      이때 나온 hash value 를 driving table 이 만들어 놓은 bitmap 과 

      대조하여 1 이면 join 을 해야 하는 column 으로 인식하고  아니면 join

      할 필요가 없는 row 이므로 버린다.

      이를 bit vector filtering 이라한다.   


   이때 hash table 을 구성하기 위해 항상 full table 을 scan 하는 것은 아니다. 

   먼저 where 조건의 index 를 타서 조건에 맞게 row 를 걸러낸 다음 그

   결과에 대해 hash table 을 구성한다. 또 hash array size 가 크면 문제가 

   안되는데, 작으면 disk 의 temp segment 에 내려 보내야 하므로 

   problem 이 발생한다.


   6. B 의 joined value 를 hash function 1 을 통과시켜 이 row 가 bit vector에 있고, 

   memory 위의 partition 에 있으면 join 이 수행되고 결과가 

   return 된다. memory 에 있지 않으면 disk 에 있는 적절한 S partition 에 

   씌여진다.

    

   7. 1번째 B 가 pass 된후 S 의 수행되지 않는 partition 들이  최대한 

      temp segment 에서 memory 로 올려지고 hash table 이 생성된다. 

      그리고 B 의 partition 이 다시 읽혀져 memory join 이 실행된다.


    즉 수행되지 않는 disk 의  partition (S,B) 이 읽혀진다. 


   (4) parameter

   -HASH_JOIN_ENABLED

     : true 로 지정시 사용가능


   -HASH_AREA_SIZE

      : sort_area_size 의 2배가 기본


   -HASH_MULTIBLOCK_IO_COUNT

      : DB_BLOCK_READ_COUNT 가 기본 


   -USE_HASH

      : hint 


   (5) partition 갯수 결정 

   첫번째로 우리는 partition (bucket) 의 갯수를 결정해야 한다. 

   여기에 우리는 hashed row 를 넣을 것이다. 

   이는  hash_area_size, db_block_size and hash_multiblock_io_count 

   parameters에 의해 결정된다.


   또 이 값은 20% 정도의 overhead 를 고려해야 한다.- storing partitions,

   the bitmap of unique left input and the hash table 


   함수 :


   Partitions 갯수  =  0.8 x hash_area_size)

                      ----------------------------

                  (db_block_size x hash_multiblock_io_count)



   row 가 가장 작은 table 이 읽혀지고 (R 이라고 부르자)  , 각 row 는

   hash algorithm 을 따른다.


   각 row 를 bucket 에 골고루 펼쳐지게 하기 위해 2가지의 algorithm 을 

   따른다.


   hash 되는 row 가 partition 에 골고루 분산되기 위해 1 번째 hash function 을 따르며, 

   2 번째 hash value 는 다음 hash 되는 경우를 위해 row 와 함께

   저장된다.

   이와 동시에 두가지의 hash  value 를 이용한 bitmap 이 만들어진다.

    

   (6) Bitmap building 예제 :


                 Hash

                 Algorithm 1 ->


                 1  2  3  4 


              1  0  0  0  0

   Second

   Hash       2  0  0  0  0     ------>   

   Algorithm 

      |       3  0  0  0  0

      V

              4  0  0  0  0


   driving table 은 hash function 1, 2 를 통과하여 bitmap 을 만든다 . 

   만일 hash area 가 모두 차면 가장 큰 partition 이 disk 로 내려간다. 


   disk 의 partition 은 partition 에 할당되는 row 에 의해 disk 에서 update

   되어진다. 만일 hash area 의 부족으로 1 partition 만이 memeory 에 

   올라간다면 나머지 partition 은 모두 disk 에 놓여지게 된다. 이런 

   경우는 생기지 않도록 조심하여야 한다.

   이 작업이 R table 의 모든 row 에 대해 행해진다.


   이 작업시 가능한 모든 partition 이 memeory 에 위치하도록 해야 한다.

   이 작업이후 B table 을 읽어들인다.이도 역시 hash function 을 통과시켜

    hash value 가 memory 에 있는 partition 을 hit 하는지 check 한다. 

   만일 그러면 이 row 는 joined row 로 반환한다.

   만일 아니면 해당 row 를 새로운 partiion 에 write 한다. 

   이때 S 와 같은 hash function 을 사용하며 이의 의미는 S와 B 의 같은 value는 

   같은  partition number 를 갖게 하기 위함이다.


   (7) unique join keys 의 bitmap 


   bitmap 은 partition 에 들어있는 value 의 flag 이라 할수 있다.

   이는 S 의 row 가 disk 의 partititon 에 씌이기 전에 생성되어 진다.

  ------------------------------------------------------------------------------------------------



 2.4 세미 조인(Semi Join)

  : 




3. 힌트의 종류

 3.1 최적화 목표(Goal) 제어 힌트

  3.1.1 ALL LOWS

   : 쿼리의 전체 결과를 모두 수행하는 것에 대한 최적화를 목표로 최저 비용의 실행계획을 수립하도록 유도

    ex) SELECT /*+ ALL_ROWS */ ~

   

  3.1.2 CHOOSE

   : 액세스하는 테이블의 통계정보 유무에 따라 규칙기준이나 비용기준을 적용하여 최적화 수행

   만약 CHOOSE 모드에서 테이블 통계정보를 참조할 수 있는 경우에는 ALL LOWS 방식으로 처리


  3.1.3 FIRST_ROWS

   : 최적 응답시간을 목표로 최저 비용의 실행계획을 수립하도록 유도

    ex) SELECT /*+ FIRST_ROWS */ ~

          SELECT /*+ FIRST_ROWS(10) */ ~


  3.1.4 RULE

   : 규칙기준 옵티마이저를 이용한 최적화를 요구


 3.2 조인 순서 조정을 위한 힌트

  : 다수의 테이블을 조인하는 경우에 조인 순서에 혼선이 있을때 적용하는 것이 가장 일반적이다.

    Sort Merge 조인이나 해쉬 조인에서는 적은 테이블을 먼저 처리하도록 유도할 때 사용하는 것이 좋다.


  3.2.1 ORDERED

   : FROM절에 기술된 테이블 순서대로 조인을 수행하도록 유도.

    만약 LEADING 힌트와 함께 사용하면 LEADING 힌트는 무시된다.


    ex) SELECT /*+ ORDERED */ ~

             FROM TBL1, TBL2, ~


          ORDERED 힌트는 엑세스 순서만 제시한 뿐, 조인 방법과는 무관하기 때문에 조인방법을 유도하기 위한 USE_NL, USE_MERGE

          등의 힌트와 함께 사용하는 것이 일반적

          SELECT /*+ ORDERED USE_NL(A B C)*/ ~

             FROM TBL1 A, TBL2 B, TBL3 C~


  3.2.2 LEADING

   : FROM 절에 기술한 테이블의 순서와 상관없이 조인 순서를 제어하는 힌트

     ex) SELECT /*+ LEADING(B C A)*/ ~

             FROM TBL1 A, TBL2 B, TBL3 C~



 3.3 조인 방법 선택용 힌트

  : 조인 방식을 선택하기 위해 적용하는 힌트를 사용하는 것은 먼저 조인 방식에 대한 확실한 이해가 바탕되어야 한다.

    부분범위 처리 가능여부, 인덱스의 구성 상태, 처리범위와 사용빈도, 메모리 가용상태와 작업영역(hash_area_size, sort_area_size)

    에도 영향을 받는다.


  3.3.1 USE_NL

   : Nested Loops 방식을 사용하여 조인을 수행하도록 유도

   ex) SELECT /*+ USE_NL(A B C )*/ ~

             FROM TBL1 A, TBL2 B, TBL3 C~


  3.3.2 NO_USE_NL

   : Nested Loops 방식외의 조인을 선택하도록 옵티마이저에게 제시.

     하지만 옵티마이저가 Nested Loops 조인이 최적이라고 판단할때는 해당 힌트는 무시한다.

   ex) SELECT /*+ NO_USE_NL(A B C )*/ ~

             FROM TBL1 A, TBL2 B, TBL3 C~

   

  3.3.3 USE_NL_WITH_INDEX

   : Nested Loops 조인시 선행 처리되는 외측루프의 처리주관 인덱스를 지정할때 사용

    과거에는 USE_NL, INDEX 힌트를 함께 사용하였지만 두가지가 통합된 힌트이다.

   ex) SELECT /*+ USE_NL_WITH_INDEX(A idx_a)*/ ~

             FROM TBL1 A, TBL2 B, TBL3 C~


  3.3.4 USE_HASH

   : 해쉬조인 방식으로 수행되도록 유도. 대부분의 경우 옵티마이저가 통계정보를 토대로 빌드입력과 검색입력을 결정하므로

   일부러 'ORDERED' 힌트를 주어 함부로 순서를 결정하는 것은 바람직하지 못하다.

    그러나 옵티마이저에서 판단에 문제가 있을 때나 인라인뷰에서 가공한 결과 집합처럼 적절한 통계정보를 가질 수 없는 경우에는

    활용 가치가 있다.

   ex) SELECT /*+ USE_HASH(A B)*/ ~

             FROM TBL1 A, TBL2 B ~


    cf) NO_USE_HASH


  3.3.5 USE_MERGE

   : Sort Merge 방식으로 조인을 수행하도록 유도. 필요하다면 ORDERED와 같이 사용할 것을 추천

   ex) SELECT /*+ USE_HASH(A B)*/ ~

             FROM TBL1 A, TBL2 B ~

   cf) NO_USE_MERGE

 


 3.4 병렬처리 관련 힌트

  : 해당 유형의 힌트는 처리방법을 개선해서 일의 양을 줄이는 것이 아니라 시스템 자원을 최대한 활용해서

    결과값을 얻는 시간을 최대한 줄이겠다는 목적으로 사용한다.


  3.4.1 PARALLEL

   : 대량의 데이터에 대한 테이블을 액세스 할 때와 DML을 처리할 때 SQL의 병렬처리를 지시하는 힌트. 

    일반적으로 병렬 스레드(Parallel threads)를 나타내는 숫자와 함께 사용한다. 만약 숫자를 정의하지 않으면

    옵티마이저는 PARALLEL_THREADS_PER_CPU 파라미터에 정의된 값을 이용해서 자동으로 계산해서 사용한다.

    테이블 정의할 때 PARALLEL 지정했다면, 힌트를 사용하지 않아도 병렬처리가 가능한 경우에는 병렬도를 적용한다.

    그러나 IDU 등의 DML문장을 병렬로 수행하기 위해서는 반드시 해당 세션을 'alter session enable parallel dml'로

    지정해야만 병렬처리 가능하다.

    만약 병렬처리에 대한 어떤 제한요소가 발생하게 되면 이 힌트는 무시된다.


    ex) SELECT /*+ FULL(A B)  PARALLEL(A, 4) */ ~

             FROM TBL1 A, TBL2 B ~


    cf) NOPARALLEL



 3.5 액세스 수단을 위한 힌트

  3.5.1 FULL

   : 힌트내에 정의된 테이블을 전체테이블 스캔 방식으로 유도하는 힌트


  3.5.2 HASH

   : 해쉬 클러스터 테이블을 액세스할 때 해쉬 스캔 방식으로 액세스 하도록 유도


  3.5.3 CLUSTER

   : 클러스터링 테이블을 액세스할 때 클러스터 인덱스를 통해 스캔하도록 유도


  3.5.4 INDEX

   : 인덱스 범위 스캔에 의한 테이블 액세스를 유도하는 힌트.  cf) NO_INDEX


  3.5.5 INDEX_ASC

   : 인덱스를 경유하여 테이블을 액세스할 때 인덱스 컬럼값의 오름차순으로 범위 스캔하도록 유도. cf) INDEX_DESC


  3.5.6 INDEX_COMBINE

   : 2개 이상의 인덱스를 비트맵 인덱스로 변경/결합하여 테이블을 액세스하는 방식으로 유도


  3.5.7 INDEX_FFS

   : 인덱스 전체 범위를 스캔하는 방식으로 유도, 인덱스를 스캔하지만 다중블록을 스캔한다. cf) NO_INDEX_FFS

  

  3.5.8 INDEX_JOIN

   : 2개 이상의 인덱스들만으로 조인을 수행하도록 유도하는 힌트. 인덱스를 구성하는 컬럼이 해당 질의에서 필요로 하는

   모든 컬럼을 포함하고 있어야 한다. 인덱스 조인은 2개 이상의 인덱스를 범위 스캔한 결과를 ROWID로 해쉬 조인을 수행하여

   결과를 얻는다.


  3.5.9 INDEX_SS

   : 인덱스 스킵 스캔 방식으로 인덱스를 액세스하도록 유도하는 힌트이다.


  3.5.10 INDEX_SS_ASC

   : 인덱스 스킵 스캔 방식으로 범위 스캔하는 경우 오름차순으로 인덱스를 읽는 힌트 cf) INDEX_SS_DESC


 3.6 쿼리 형태 변형을 위한 힌트

  3.6.1 USE_CONCAT

   : 조건절에 있는 OR연산자 또는 IN 연산자의 조건을 별도의 실행단위로 분리하여 각각의 최적의 액세스 경로를 수립하여

    이를 연결하는 실행계획을 유도하는 힌트. 반드시 조건이 OR로 나뉘었을때 적용해야 하며, 잘못 사용시 비효율 발생 주의

    ex) SELECT /*+ USE_CONCAT */ ~

             FROM EMP

           WHERE job = 'CLERK' OR deptno = 10;

  3.6.2 NO_EXPAND

   : 조건절에 있는 OR 연산자 조건을 연결 실행계획으로 처리되지 않도록 할 때 사용하는 힌트이다. USE_CONCAT의 반대



 3.7 기타 힌트

  3.7.1 APPEND

   : insert 문에서 사용되는 힌트. 입력작업을 'DIRECT-PATH'방식으로 수행되도록 하여 SGA를 거치지 않고 직접 저장공간으로

    입력이 되도록 함으로써 매우 빠른 입력 처리를 보장한다. 유의할 점은 반드시 최고 수위점(High Water Mark) 다음 위치에 

    데이터를 저장한다.


    ex) INSERT /*+ APPEND */ INTO TBL1

          SELECT *

             FROM TBL2

            WHERE ~~

'공부 > SQL' 카테고리의 다른 글

오라클 sys , system 암호(패스워드) 분실시  (0) 2016.05.02
View에 Comment달기  (0) 2016.05.02
ORA-01476 제수가 0 입니다  (0) 2016.04.25
테이블 정보 조회 쿼리  (0) 2016.04.18
count over partition by  (0) 2016.04.18
댓글