태그 : 오라클

[ORACLE] Nested Loop Join과 Sort Merge 조인

 

Nested Loop Join과 Sort Merge Join

 

Nested Loop Join

 

Nested Loop Join이란 먼저 어떤 테이블의 처리범위를 하나씩 액세스하면서 그 추출된 값으로 연결할 테이블을 조인하는 방식이다.

 

1. 특징

1) 순차적으로 처리된다. 선행테이블(Driving table)의 처리범위에 있는 각각의 로우들이 순차적으로 수행될 뿐만 아니라 테이블간의 연결도 순차적이다.

2) 먼저 액세스되는 테이블(Driving Table)의 처리범위에 의해 처리량이 결정된다.

3) 나중에 처리되는 테이블은 앞서 처리된 값을 받아 액세스된다. 즉, 자신에게 주어진 상수값에 의해 스스로 범위를 줄이는 것이 아니라 값을 받아서 처리범위가 정해진다.

4) 주로 랜덤 액세스 방식으로 처리된다. 선행 테이블의 인덱스 액세스는 첫번째 로우만 랜덤 액세스이고 나머지는 스캔이며 연결작업은 모두 랜덤 액세스이다.

5) 주어진 조건에 있는 모든 컬럼들이 인덱스를 가지고 있더라도 모두가 사용되는 것은 아니다. 연결되는 방향에 따라 사용되는 인덱스들이 전혀 달라질 수 있다.

6) 연결고리가 되는 인덱스에 의해 연결작업이 수행되므로 연결고리 상태가 매우 중요하다. 연결고리의 인덱스 유무에 따라 액세스 방향 및 수행속도에 많은 차이가 발생된다.

7) 연결작업 수행 후 마지막으로 check되는 조건은 부분범위처리를 하는 경우에는 조건의 범위가 넓을수록, 아예 없다면 오히려 빨라진다.

 

2. 사용기준

1) 부분범위처리를 하는 경우에 주로 유리해진다.

2) 조인되는 어느 한쪽이 상대방 테이블에서 추출된 결과를 받아야 처리범위를 줄일 수 있는 상태라면 항상 유리해진다.

3) 주로 처리량이 적은 경우(많더라도 부분범위처리가 가능한 경우)에 유리해진다. 그것은 처리방식이 주로 랜덤 액세스방식이므로 많은 양의 랜덤 액세스가 발생한다면 수행속도가 당연히 나빠지기 때문이다.

4) 가능한 한 연결고리 이상 상태를 만들지 않도록 주의해야 한다.

5) 순차적으로 처리되기 때문에 어떤 테이블이 먼저 액세스되느냐에 따라 수행속도에 많은 영향을 미치므로 최적의 액세스 순서가 되도록 적절한 조치가 요구된다.

6) 부분범위처리를 하는 경우에는 운반단위 크기가 수행속도에 많은 영향을 미칠 수 있다. 운반단위가 적을 수록 빨리 운반단위를 채울 수 있으나, 폐치(Fetch) 횟수에서는 불리해지는 이중성을 가지고 있다.

7) 선행 테입ㄹ의 처리 범위가 많거나 연결 테이블의 랜덤 액세스의 양이 아주 많다면 Sort Merge 조인보다 불리해지는 경우가 많다.

 

Sort Merge Join

 

Sort Merge Join이란 양쪽 테이블의 처리범위를 각자 액세스하여 정렬한 결과를 차례로 스캔하면서 연결고리의 조건으로 머지해 가는 방식을 말한다. 이 방식은 경우에 따라 Nested Loop Join보다 훨씬 빨라지는 경우도 많이 있으며 랜덤 액세스가 줄어들어 시스템의 부하를 감소시키지만 일반적으로 Nested Loop Join 보다는 사용되는 빈도가 적은 편이다.

이 방식의 가장 큰 특징은 상대방에게 아무런 값도 받지 않고 자신이 가지고 있는 조건만으로 처리범위가 정해지며, 랜덤 액세스를 줄일 수는 있으나 항상 전체범위처리를 한다는 것이다.

 

1. 특징

1) 동시적으로 처리된다. 테이블 각자가 자신의 처리범위를 액세스하여 정렬해 둔다.

2) 각 테이블은 다른 테이블에서 어떠한 상수값도 제공받지 않는다. 즉, 자신에게 주어진 상수값에 의해서만 범위를 줄인다.

3) 결코 부분범위처리를 할 수가 없으며, 항상 전체범위처리를 한다.

4) 주로 스캔방식으로 처리된다. 자신의 처리범위를 줄이기 위해 인덱스를 사용하는 경우만 랜덤 액세스이고 머지작업은 스캔방식이다.

5) 주어진 조건에 있는 모든 컬럼들이 인덱스를 가지고 있더라도 모두가 사용되는 것은 아니다. 연결고리가 되는 컬럼은 인덱스를 전혀 사용하지 않는다.

6) 조인의 방향과는 전혀 무관하다.

7) 스스로 자신의 처리범위를 줄이기 위해 사용되는 인덱스는 대개 가장 유리한 한가지만 사용되어진다. 그러나 그 외의 조건들은 비록 인덱스를 사용하지 못하더라도 작업대상을 줄여 주기 때문에 중요한 의미를 가진다.

 

2. 사용기준

1) 전체범위처리를 하는 경우에 주로 유리해진다.

2) 상대방 테이블에서 어떤 상수값을 받지 않고도 처리범위를 줄일 수 있는 상태인 경우 주로 유리해 질 수 있다. 상수값을 받아 처리(Nested Loop Join)한 범위의 크기와 처리범위를 줄여 처리(Sort Merge Join)한 범위의 크기를 대비해보아 상수값을 받아 줄여진 범위가 약 30% 이상이라면 Sort Merge Join이 일반적으로 유리해진다. 그러나 부분범위처리가 되는 경우라면 전혀 달라질 수 있다. 이런 경우는 처리할 전체범위를 비교하지 말고 첫번째 운반단위에 도달하기 위해 액세스하는 범위애 대해서 판단해야 한다.

3) 주로 처리량이 많은 경우 (항상 전체범위처리를 해야 하는 경우)에 유리해진다. 그것은 처리방식이 주로 스캔방식이므로 많은 양의 랜덤 액세스를 줄일 수가 있기 때문이다.

4) 연결고리 이상 상태에 영향을 받지 않으므로 연결고리를 위한 인덱스를 생성할 필요가 없을 때 유용하게 사용할 수 있다.

5) 스스로 자신의 처리범위를 어떻게 줄일 수 있느냐가 수행속도에 많은 영향을 미치므로 보다 효율적으로 액세스할 수 잇는 인덱스 구성이 중요한다.

6) 전체범위처리를 하므로 운반단위의 크기가 수행속도에 영향을 미치지 않는다. 가능한 운반단위를 크게 하는 것이 페치(Fetch) 횟수를 줄여준다. 물론 지나치게 큰 운반단위는 시스템에 나쁜 영향을 미친다.

7) 처리할 데이터량이 적은 온라인 애플리케이션에서는 Nested Loop Join이 유리한 경우가 많으므로 함부로 Sort Merge Join을 사용하지 말아야 한다.

8) 옵티마이저 목표(Goal)가  "ALL_ROWS"인 경우는 자주 Sort Merge Join으로 실행계획이 수립되므로 부분범위처리를 하고자 한다면 이 옵티마이져 목표가 어떻게 지정되어 있는지에 주의하여야 한다.

 

================================================

"대용량 데이터베이스" 책에서 발췌한 겁니다.

잘 기억이 안나고 헛갈려서요 ^^;;;

by 밀리 | 2008/10/27 17:05 | DB[ORACLE/MS-SQL] | 트랙백 | 덧글(0)

리눅스에 오라클 10g 설치

리눅스 오라클 설치 (10G)

오라클은 root 로 설치할수없다(설정은 root 로)

mkdir -p /app/oracle

groupadd dba //그룹설정  유저도 설정 해놓는 것이 좋다

useradd oracle

usemod -g dba -d /app/oracle oracle // 모드 변경

chown -R oracle.dba oracle

게정으로 로그인하여 profile 을 설정한다 (.bash_profile)
mkdir -p /app/oracle/tmp
mkdir -p /app/oracle/product/10.1.0
vi .bash_profile

 

-----vi 모드

ORACLE_BASE=/app/oracle; export ORACLE_BASE

ORACLE_HOME=/app/oracle/product/10.1.0; export ORACLE_HOME

ORACLE_TERM=vt100; export ORACLE_TERM

TMPDIR=$ORACLE_BASE/tmp; export TMPDIR

TEMP=$ORACLE_BASE/tmp; export TEMP

NLS_LANG=American_America.KO16KSC5601; export NLS_LANG

PATH=$PATH:.:$ORACLE_HOME/bin

###export DISPLAY=192.168.1.169:0.0  //자신의 아이피###

ORACLE_SID=NEWSVC; export ORACLE_SID

PS1='[${ORACLE_SID}]''${HOSTNAME}'':$PWD>'

umask 022
set -o vi

---->vi 종료

패키지 확인~~~~

커널 파라미터 확인
vi /etc/sysctl.conf

--->vi 모드

<추가 기본 커널 설정>

kernel.sem = 250 32000 100 128
kernel.shmmax = 2147483648
fs.file-max = 65536
net.ipv4.ip_local_port_range =1024  65000
net.core.rmem_default = 262144
net.core.rmem_max  = 262144
net.core.wmem_default = 262144
net.core.wmem_max = 262144

Xwindow oracle 계정 접속
오라클 원폴더/bin/runinstall

GUI창이뜬다 --> 설치


by 밀리 | 2008/10/04 10:07 | Linux - Ubuntu | 트랙백 | 덧글(0)

오라클 HINT을 활용하여 [SQL Tuning] 튜닝을 해보자~~


<<Optimization Approaches and Goals - Optimization  접근과 목적>>
  

/*+ ALL_ROWS */
 
  ALL_ROWS는Full Table Scan을 선호하며 CBO(Cost Based Optimization)는 default로
  ALL_ROWS를 선택 합니다.         
        
   SQL>SELECT /*+ ALL_ROWS */  ename, hiredate FROM emp  WHERE ename like ’%%%’
       
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: ALL_ROWS (Cost=1 Card=5 Bytes=80)
   1    0   TABLE ACCESS (FULL) OF ’EMP’ (Cost=1 Card=5 Bytes=80)
 
 
 
/*+ CHOOSE */

  Hint Level의 CHOOSE는 RBO(Rule Based Optimization)인지 CBO(Cost Based Optimization)
  인지를 선택 합니다.

   만약 주어진 table의 통계 정보가 없다면 Rule Based 접근 방식을 사용 합니다.
 
 
 
/*+ FIRST_ROWS */

   Full Table Scan보다는 index scan을 선호하며
   Interactive Application인 경우 best response time을 제공 합니다.

   또한 sort merge join보다는 nested loop join을 선호 합니다.
 
   SQL>SELECT /*+ FIRST_ROWS */  ename FROM emp WHERE empno=7876
 
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=1 Card=1 Bytes=20)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF ’EMP’ (Cost=1 Card=1 Bytes=20)
   2    1     INDEX (RANGE SCAN) OF ’PK_EMP’ (UNIQUE) (Cost=1 Card=1)
 
 
 
/*+ RULE */

   Rule Based 접근 방식을 사용하도록 지정 합니다.

 


<<Access Methods - 접근 방법>>
 
 
/*+ CLUSTER(table_name) */

  Cluster Scan을 선택하도록 지정한다. 따라서 clustered object들에만 적용 됩니다.
 

 
/*+ FULL(table_name) */

  Table을 Full Scan하길 원할 때 사용 합니다.

 

/*+ HASH(table) */

  Hash scan을 선택하도록 지정한다.
  이 hint는 HASHKEYS parameter를 가지고 만들어진 cluster내에 저장된 table에만 적용이 됩니다.
 
 

/*+ INDEX(table_name index_name) */

  지정된 index를 강제적으로 쓰게끔 지정 합니다.
 
 
 
/*+ INDEX_ASC(table_name index_name) */

  지정된 index를 오름차순으로 쓰게끔 지정 합니다.
  Default로 Index Scan은 오름차순 입니다
 

 
/*+ INDEX_DESC(table_name index_name) */
 
  지정된 index를 내림차순으로 쓰게끔 지정 합니다.
 
 
   SQL>SELECT /*+ index_desc(emp pk_emp) */  empno
           FROM   emp
           WHERE  rownum = 1 ;
        
    위 문장은 제일 큰 것 하나만 조회되므로, max function의 기능을 대신할 수 있습니다.    



 /*+ INDEX_FFS(table index) */

  Full table scan보다 빠른 Full index scan을 유도 합니다.
 
 

/*+ ROWID(table) */

  Rowid로 Table Scan을 하도록 지정 합니다.

 


<<Join Orders>>


/*+ ORDERED */

  From절에 기술된 테이블 순서대로 join이 일어나도록 유도 합니다.

 

 


<<Join Operations>>
 
 
/*+ USE_HASH (table_name) */

  각 테이블간 HASH JOIN이 일어나도록 유도 합니다.
 
 

/*+ USE_MERGE (table_name) */

  지정된 테이블들의 조인이 SORT-MERGE형식으로 일어나도록 유도 합니다.

 


<<Parallel Execution>>
 
 
/*+ NOPARALLEL(table_name) */
 
  NOPARALLEL hint를 사용하면, parallel query option을 사용하지 않도록 할 수 있다.
 
  SQL>SELECT /*+ NOPARALLEL */ *  FROM emp;
 
 
 
/*+ PARALLEL(table_name, degree) */
 
  PARALLEL hint를 사용하면 query에 포함된 table의 degree를 설정할 수 있습니다.
 
  예를 들어, 다음과 같이 hint를 적어 degree 4로 parallel query option을  실행하도록 할 수 있습니다.
  이 때 parallel이란 글자와 괄호( ’(’ )사이에 blank를 넣지 않도록 주의해야 합니다.
  
  SQL>SELECT /*+ PARALLEL(emp, 4) */   * FROM emp;
 
 
 
* DEGREE의 의미 및 결정
 
Parallel Query에서 degree란 하나의 operation 수행에 대한 server process의 개수 입니다.
이러한 degree 결정에 영향을 주는 요인들에는 다음과 같은 것들이 있습니다.
 
(1)  system의 CPU 갯수
(2)  system의 maximum process 갯수
(3)  table이 striping되어 있는 경우, 그 table이 걸쳐있는 disk의 갯수
(4)  data의 위치 (즉, memory에 cache되어 있는지, disk에 있는지)
(5)  query의 형태 (예를 들어 sorts 혹은 full table scan)
 
한 사용자만이 parallel query를 사용하는 경우, sorting이 많이 필요한
작업과 같은 CPU-bound 작업의 경우는 CPU 갯수의 1 ~ 2배의 degree가 적당하며,
sorting보다는 table scan과 같은 I/O bound 작업의 경우는 disk drive 갯수의 1 ~ 2배가 적당합니다.
 
동시에 수행되는 parallel query가 많은 경우에는 위의 각 사용자의 degree를
줄이거나 동시에 사용하는 사용자 수를 줄여야 합니다.

by 밀리 | 2008/09/29 10:58 | DB[ORACLE/MS-SQL] | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶