ORACLE/TUNING2009. 2. 6. 14:52
반응형
[Hint]조인 방법 변경(USE_NL)
조인 방법 변경(USE_NL)

테이블을 조인 하는 경우 중첩 루프 조인(Nested Loop Join)이 일어나도록 하는 힌트 문장 입니다. 중첩 루프 조인은 중첩 반복이라고도 하는데 하나의 테이블(outer/driving table)에서 추출된 로우를 가지고 일일이 다른 테이블(inner/probed table)을 반복해서 조회하여 찾아지는 레코드를 최종 데이터로 간주하는 방법 입니다.

즉 조인 입력 한 개를 외부 입력 테이블로 사용하고, 한 개는 내부(최하위) 입력 테이블로 사용하고 외부 루프는 외부 입력 테이블을 행 단위로 사용하고 각 외부 행에 대해 실행되는 내부 루프는 내부 입력 테이블에서 일치되는 행을 검색 하는거죠…  이것을 원시 중첩 루프 조인이라고 하는데 검색에서 인덱스를 사용하는 경우에는 인덱스 중첩 루프 조인이라고 합니다.

예를 들어 EMP 테이블과 DEPT 테이블을 조인하는 경우 dept 테이블이 건수가 작다면 우선 이 테이블을 외부 루프로 해서 하나씩 읽으면서 이에 대응하는 emp 테이블의 데이터를 추출 하는 경우라면 중첩 루프 조인에 해당 합니다. 이때 emp 테이블의 경우 건수가 많다고 가정을 하면 대부분 인덱스를 이용하도록 emp 테이블의 외래키인 deptno 컬럼은 대부분 인덱스를 걸게 되죠^^

중첩 루프 조인은 테이블중 적어도 하나의 조인 컬럼에 대해 인덱스(or Hash Index)가 존재할 때 연관되는 방식으로 이 중첩 루프 조인에서 테이블중 하나의 테이블 또는 중간 결과 셋을 대상으로 FULL SCAN이 일어나게 됩니다. 이 테이블이 드라이빙 테이블이 되는데… 이 테이블의 데이터 건마다 나머지 테이블에서 원하는 데이터를 추출하기 위해 대부분 인덱스를 사용하게 되는 겁니다.

보통 USE_NL 힌트 구문은 ORDERED 힌트 구문과 같이 사용되는데 USE_NL이 취하는 인자는 FROM절에서 두번째 나오는 테이블(비드라이빙 테이블, inner/probed table)을 명시해 주어야 합니다. 안수로 사용되지 않은 첫 번째 테이블은  outer/driving table이 되는 것입니다.

[형식]
/*+ USE_NL ( table [table]... ) */


[예]

아래는 Oracle 10g에서 테스트 한 결과 입니다.

analyze table emp compute statistics
analyze table dept compute statistics

select /*+ORDERED USE_NLe) */
       e.ename,
           d.dname
from   dept d, emp e
where  e.deptno = d.deptno        

------------------------------------------------------------
Operation        Object Name        Rows        Bytes        Cost        
---------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS                14                   4
  TABLE ACCESS BY INDEX ROWID        SCOTT.EMP        4          32          1          
    NESTED LOOPS                14          266          4                                  
      TABLE ACCESS FULL        SCOTT.DEPT        4          44          3                    
      INDEX RANGE SCAN        SCOTT.IDX_EMP_DEPTNO        5                   0  


        FROM절에서 처음 나타나는 테이블이 드라이빙 테이블(DRIVING/OUTER? TABLE)이며 비드라이빙 테이블(PROBE/INNER TABLE)이 USE_NL의 인자로 들어갑니다!!

select /*+ORDERED USE_NL(D) */
       e.ename,
           d.dname
from   emp e, dept d
where  e.deptno = d.deptno        

--------------------------------------------------------------
Operation        Object Name        Rows        Bytes        Cost        
--------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS                14                   3
  NESTED LOOPS                14          266          3                                  
    TABLE ACCESS BY INDEX ROWID        SCOTT.EMP        14          112          2          
      INDEX FULL SCAN        SCOTT.IDX_EMP_DEPTNO        13                   1
    TABLE ACCESS BY INDEX ROWID        SCOTT.DEPT        1          11          1          
      INDEX UNIQUE SCAN        SCOTT.PK_DEPT        1                   0          
                                                    

이번에는 USE_MERGE와 ORDERED가 같이 쓰이는 경우인데 이 경우엔 FROM 절 뒤 테이블의 순서는 실행계획은 다르게 나티날지 모르지만 성능에는 영향을 미치지 않습니다. 왜냐구요? 위 내용을 읽어 보세요!!


select /*+ORDERED USE_MERGE(D) */
       e.ename,
           d.dname
from   emp e, dept d
where  e.deptno = d.deptno        


--------------------------------------------------------------
Operation        Object Name        Rows        Bytes        Cost        
-------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS                14                   6
  MERGE JOIN                14          266          6                                                      
    TABLE ACCESS BY INDEX ROWID        SCOTT.EMP        14          112          2          
      INDEX FULL SCAN        SCOTT.IDX_EMP_DEPTNO        13                   1
    SORT JOIN                4          44          4                                                      
      TABLE ACCESS FULL        SCOTT.DEPT        4          44          3                                                      


select /*+ ORDERED USE_MERGE(E) */
       e.ename,
           d.dname
from   dept D, emp E
where  e.deptno = d.deptno        


----------------------------------------------------------------
Operation        Object Name        Rows        Bytes        Cost        
--------------------------------------------------------------
SELECT STATEMENT Optimizer Mode=ALL_ROWS                14                   5
  MERGE JOIN                14          266          5                                                      
    TABLE ACCESS BY INDEX ROWID        SCOTT.DEPT        4          44          2          
      INDEX FULL SCAN        SCOTT.PK_DEPT        4                   1          
    SORT JOIN                14          112          3                                                      
      TABLE ACCESS BY INDEX ROWID        SCOTT.EMP        14          112          2          
        INDEX FULL SCAN        SCOTT.IDX_EMP_DEPTNO        13                   1    

http://blog.paran.com/oraclejava/9910752

 

 

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

 

 

NESTED LOOP JOIN

 

선행적 특징을 작는데 먼저 액세스되는 테이블의 처리범위에 의해 처리량이 결정됨
Driving Table에 의해 범위가 결정되며 Driving Table의 범위가 적을수록 수행속도는 빨라진다
고로 Driving Table을 어던 테이블로 결정하느냐가 중요하다


-. /*+ use_nl (테이블) */
-. 나중에 처리되는 테이블은 앞서 처리된 값을 받아 액세스하게됨, 즉 값을 받아서 처리범위가 정해짐
-. Driving Table의 인덱스 액세스는 첫번 로우만 Random Access이고, 나머지는 Scan, 연결작업은 Random Access임
-. 연결되는 방향에 따라 사용되는 인덱스들이 달라질 수 있음
-. 연결고리 인덱스 유무에 따라 액세스 방향 및 수행속도에 많은 차이가 있음
-. 연결작업 수행 후 체크되는 조건으로 부분범위처리를 하는 경우에는 조건의 범위가 넓거나 없다면 오히려 빨라짐

-. 전체가 아닌 부분범위 처리를 하는 경우 유리함
-. 조인되는 테이블중 어느 한쪽의 추출된 결과를 받아야 처리범위를 줄일 수 있는 상태라면 항상 유리함
-. Driving Table의 처리량이 많거나 연결 테이블의 Random Access량이 많을 경우에는 분리함
-. 일반적으로 처리량이 적은 경우로서 Random Access를 많이 하므로, 온라인 어플리에서 유리함
-. Driving Table의 선택이 관건임


 

SORT MERGE JOIN

 

일반적으로 배치작업에서 주로 사용되며, 각 테이블을 Sort한 후 Merge 하는 조인을 말한다

 

-. /*+ use_merge(테이블) */
-. 동시에 각각의 테이블이 자신의 처리범위를 액세스하여 정렬해둠
-. 각 테이블은 어떠한 상수값도 서로 영향을 주지 않으며, 주어진 상수값에 의해서만 각자 범위를 줄이게됨
-. 전체범위처리를하며 부분범위처리를 할수 없음
-. 자신의 처리범위를 줄이기 위해 인덱스를 사용하는 경우에만 Random Access이고, Merge작업은 Scan방식
-. 선택적으로 연결고리가 되는 컬럼은 인덱스를 사용하지 않음
-. 조인의 방향과는 상관없음
-. Equal 조인에서만 가능

-. 처리량이 많은 경우로 Random Access를 하지 않음으로 전체범위처리에 유리
-. 자신의 처리범위를 인덱스를 통해 어떻게 줄이느냐가 관건
-. 상수값을 받아 줄여진 범위가 30%이상이면 Sort Merge가 유리

 

 

HASH JOIN

 

Hash Function을 이용해서 메모리와 CPU를 많이 사용해서 일반적으로 배치작업에서 주로 사용됨


-. /*+ use_hash(테이블) */
-. 적은테이블과 큰테이블의 조인시에 유리
-. Equal 조인에서만 가능
-. Driving Table에 인덱스를 필요로 하지 않고 각 테이블을 한번만 읽음
-. 다른조인방법보다 CPU자원을 많이 소비하며 양쪽 테이블의 scan이 동시에 일어남

 

from) http://www.jakartaproject.com/

반응형
Posted by [PineTree]
ORACLE/TUNING2009. 2. 6. 14:45
반응형

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으로 실행계획이 수립되므로 부분범위처리를 하고자 한다면 이 옵티마이져 목표가 어떻게 지정되어 있는지에 주의하여야 한다.

반응형
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 6. 10:58
반응형
Zurück

Can INSERT's be tuned?


Overview

The CREATE TABLE ... AS SELECT statement (CTAS) is a powerful tool for manipulating large sets of data. CTAS provides a mechanism for efficiently executing a SQL query and storing the results of that query in a new database table.

The INSERT /*+APPEND*/ ... AS SELECT statement offers the same capabilities with existing database tables.

APPEND into Tables

By using the APPEND hint, you ensure that Oracle always grabs "fresh" data blocks by raising the high-water-mark for the table. If you are doing parallel insert DML, the Append mode is the default and you don't need to specify an APPEND hint.

When you use the APPEND hint for INSERT, data is simply appended to a table above the HWM which has the effect of not creating UNDO. Existing free space in blocks is not used.

High Water Mark

The high water mark is the boundary between used and unused space in a segment. As requests for new free blocks that cannot be satisfied by existing free lists are received, the block to which the high water mark points becomes a used block, and the high water mark is advanced to the next block. In other words, the segment space to the left of the high water mark is used, and the space to the right of it is unused.

Suggest Way for fast INSERTs

  • Mark indexes unuasble
  • Disable primary key
  • Alter table nologging
  • Do an insert /*+ append */ into table (select ..)
  • Enable primary key
  • Rebuild indexes nologging

Example

1.  First create a Big Table for this Test

create table bigtab
as
select rownum id, a.*
from all_objects a
where 1=0;

alter table bigtab nologging;

declare
l_cnt number;
l_rows number := 1000000;
begin
insert /*+ append */
into bigtab
select rownum, a.*
from all_objects a;

l_cnt := sql%rowcount;

commit;

while (l_cnt < l_rows)
loop
insert /*+ APPEND */ into bigtab
select rownum+l_cnt,
OWNER, OBJECT_NAME, SUBOBJECT_NAME,
OBJECT_ID, DATA_OBJECT_ID,
OBJECT_TYPE, CREATED, LAST_DDL_TIME,
TIMESTAMP, STATUS, TEMPORARY,
GENERATED, SECONDARY
from bigtab
where rownum <= l_rows-l_cnt;
l_cnt := l_cnt + sql%rowcount;
commit;
end loop;
end;
/

Now we have a Table with 1'000'000 Rows. Now delete some Rows, to force Oracle to refill this freespace using the FREELISTS in a normal INSERT. However in APPEND Mode the FREELISTS are not used and the freespace are not reoccupied.

DELETE FROM bigtab WHERE id between 1000 and 2500;
DELETE FROM bigtab WHERE id between 3500 and 6500;
DELETE FROM bigtab WHERE id between 15000 and 20000;
DELETE FROM bigtab WHERE id between 350000 and 370000;
COMMIT;

CREATE TABLE insert_test AS SELECT * FROM bigtab;

2.  Test with normal Insert

SQL> CREATE TABLE insert_test AS SELECT * FROM bigtab;
Table created.

SQL> INSERT INTO insert_test SELECT rownum, a.* FROM all_objects a;
49483 rows created.

Elapsed: 00:00:03.92
   <==================== !

SQL> DROP TABLE insert_test;
Table dropped.

3.  Test with APPEND Hint and NOLOGGING

SQL> CREATE TABLE insert_test AS SELECT * FROM bigtab;
Table created.

SQL> ALTER TABLE insert_test NOLOGGING;
Table altered.

SQL> INSERT /*+ append */ INTO insert_test SELECT rownum, a.* FROM all_objects a;
49483 rows created.

Elapsed: 00:00:02.54
    <==================== !

As you can see, only to insert about 50'000 Rows, the APPEND Insert is much faster, due the free space in the Oracle blocks are not refilled, the Rows are appended and the Highwater Mark is moved.

반응형

'ORACLE > ADMIN' 카테고리의 다른 글

PCTFREE, PCTUSED  (0) 2009.02.25
oracle em 구성  (0) 2009.02.12
Query Rewrite와 MView Refresh.  (0) 2009.02.05
MView의 생성  (0) 2009.02.05
Materialized View  (0) 2009.02.05
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 5. 15:01
반응형

Query Rewrite(질의 재작성)


 1) Query Rewrite(질의 재작성)란?
 
A란 사용자가 자주사용되는 복잡한 Query 문장을 MView로 생성해 놓았을 경우..
 
그 사실을 모르는 B가 A가 만든 뷰와 똑같은 결과를 조회하는 Query문을 MView가 아닌
일반 SQL문장으로 실행했을 경우 B는 SQL문장을 수행했지만. 같은 문장에 MView가 존재하면
B가 실행한 문장이 A가 생성해놓은 MView를 실행하는 것으로 자동 전환이 됩니다.

이러한 기능을 Query Rewrite라고 합니다.

SQL문장을 수행하였어도 미리 정의된 MView가 존재한다면, MView를 조회하도록 Query가 다시 쓰여지는 거죠..


 2) Query Rewrite 예제

Query Rewrite 기능을 사용하기 위해서는 다음의 기능이 필요 필요합니다
 
 - 인스턴스 파라미터인 OPTIMIZER_MODE, QUERY_REWRITE_ENABLED,
    QUERY_REWRITE_INTEGRITY, COMPATIBLE
이 설정되어 있어야 합니다.

 - 또한 MView생성시 ENABLE QUERY REWRITE 옵션을 추가되어 있어야 합니다.

 - MView를 생성한 유저는 반드시 QUERY REWRITE의 시스템 권한이 있어야 합니다.


-- sysdba 권한으로 접속 합니다.
SQL>sys/manager@oracle as sysdba


-- QUERY_REWRITE_ENABLED를 TRUE로 변경 합니다.
SQL>ALTER SYSTEM SET QUERY_REWRITE_ENABLED=’TRUE’;
시스템이 변경되었습니다.


-- 테스트 유저로 접속 합니다.
SQL>conn scott/tiger@oracle


-- Query Rewrite가 정상적으로 실행되는지 확인하기 위해서 autotrace를 실행합니다.
-- AUTOTRACE 관련해서는 "SQL*Plus AUTOTRACE" 강좌를 참고해 보세요

SQL>SET AUTOTRACE ON


-- MView를 생성했던 SQL문장 실행
SQL> SELECT SUM(a.sal), a.deptno
     FROM emp a, dept b
     WHERE a.deptno = b.deptno
     GROUP BY a.deptno;


-- OPTIMIZER_MODE가 CHOOSE인 상태에서 Analyze를 실행하지 않아 QueryRewrite가
    실행되지 않았습니다.

-- OPTIMIZER_MODE가 CHOOSE일 경우는 모든 테이블을 ANALYZE 시켜 줘야 합니다.
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     NESTED LOOPS
   3    2       TABLE ACCESS (FULL) OF ’EMP’
   4    2       INDEX (UNIQUE SCAN) OF ’PK_DEPT’ (UNIQUE)



-- OPTIMIZER_MODE를 변경해 봤습니다.
SQL> ALTER SESSION SET OPTIMIZER_MODE=’FIRST_ROWS’;
세션이 변경되었습니다.
 
 
-- OPTIMIZER_MODE 변경후 다시 실행
SQL> SELECT SUM(a.sal), a.deptno
     FROM emp a, dept b
     WHERE a.deptno = b.deptno
     GROUP BY a.deptno;
 
SUM(A.SAL)     DEPTNO
---------- ----------
      8750         10
     10875         20
      9400         30


-- DEPT_SAL이라는 MView로 Query Rewrite를 실행한 것을 알 수 있습니다.
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=2 Card=82 Bytes=2132)
   1    0   TABLE ACCESS (FULL) OF ’DEPT_SAL’ (Cost=2 Card=82 Bytes=2132)


※ Query Rewrite와 Hint 사용
 
Index 관련 Hint를 사용하는 것 처럼, query rewite 관련 Hint를 사용하여 제어할 수도 있습니다.
 
NOREWRITE : SELECT /*+ NOREWRITE */...
REWRITE:  SELECT /*+ REWRITE(mv1) */...

 

MView를 수동으로 Refresh 하기


DBMS_MVIEW 패키지를 이용해서 수동적으로 MView의 Data를 최근의 데이터로 변경할 수 있습니다.

DBMS_MVIEW 패키지의 REFRESH, REFRESH_ALL_MVIEWS, REFRESH_DEPENDENT를 call
하면 됩니다.


-- 아래와 같이 emp테이블에 임이의 데이터를 INSERT한 후 MView를 갱신해 보세요..
SQL>INSERT INTO EMP ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM,DEPTNO )
        VALUES ( 7935, ’KIM’, ’MANAGER’, 7839,  TO_Date( ’12/17/1980 12:00:00 오전’, ’MM/DD/YYYY HH:MI:SS AM’), 3000, NULL, 20);
1 개의 행이 만들어졌습니다.


SQL> commit;
커밋이 완료되었습니다.


-- DEPT_SAL은 이전 MView생성 강좌에서 생성한 MView입니다.
-- DEPT_SAL MView는 ON DEMAND로 생성을 했기 때문에 데이타가 변경되지 않은 것을 확인
    할 수 있습니다.
-- DEPT_SAL MView를 ON COMMIT로 생성했을 경우 위에 commit시점에서 dept_sal이 변경이 됩니다.
SQL> SELECT * FROM DEPT_SAL;


--수동으로  dept_sal 하나의 MView만 갱신 한 후 다시 조회하면 변경된 것을 확인 할 수 있습니다.
SQL>BEGIN
       DBMS_MVIEW.REFRESH(’DEPT_SAL’);    
    END;
    /
PL/SQL 처리가 정상적으로 완료되었습니다.



-- BASE 테이블에 EMP테이블이 들어간 모든 MView를 갱신
BEGIN
    DBMS_MVIEW.REFRESH_DEPENDENT(’EMP’);    
END;



-- 모든 MView를 모두 갱신
BEGIN
    DBMS_MVIEW.REFRESH_ALL_MVIEWS;    
END;



<<참고문헌>>
 - Oracle Technical Note Materialized View  글 / 박경희
 - Oracle Technical Bulletins  No.12181 MATERIALIZED VIEW 활용방법
 - Oracle 8i Tuning 정식 교재


반응형

'ORACLE > ADMIN' 카테고리의 다른 글

oracle em 구성  (0) 2009.02.12
INSERT /*+ APPEND */ VS CTAS  (0) 2009.02.06
MView의 생성  (0) 2009.02.05
Materialized View  (0) 2009.02.05
ALTER ~ SHRINK SPACE  (0) 2009.02.05
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 5. 14:55
반응형

MView의 생성

MView를 생성하고 테스트 하기 위해서는,  sysdba에서 Query Rewrite권한과  
CREATE MATERIALIZED VIEW 권한을 MView를 생성하는 유저에게 부여해야 합니다.


-- sysdba 권한으로 접속 합니다.
SQL> conn sys/manager as sysdba
연결되었습니다.
 
 
-- QUERY REWRITE 권한을 부여 합니다.
SQL> GRANT QUERY REWRITE TO SCOTT;
권한이 부여되었습니다.
 
 
-- CREATE MATERIALIZED VIEW 권한을 부여 합니다.
SQL> GRANT CREATE MATERIALIZED VIEW TO SCOTT;
권한이 부여되었습니다.
 
 
-- MATERIALIZED VIEW를 생성할 유저로 접속 합니다.
SQL> conn scott/tiger
연결되었습니다.
 
 
-- MATERIALIZED VIEW 생성
SQL> CREATE MATERIALIZED VIEW dept_sal
     -- PCTFREE 0 TABLESPACE mviews
     -- STORAGE (initial 16k next 16k pctincrease 0)
     BUILD IMMEDIATE -- BUILD IMMEDIATE, BUILD DEFERRED 선택.
     REFRESH
     COMPLETE       -- FORCE, COMPLETE, FAST, NEVER 선택.
     ON DEMAND      -- ON DEMAND, ON COMMIT 선택.
     ENABLE QUERY REWRITE
     AS
     SELECT SUM(a.sal), a.deptno
     FROM emp a, dept b
     WHERE a.deptno = b.deptno
     GROUP BY a.deptno;
구체화된 뷰가 생성되었습니다.
 
 
-- MATERIALIZED VIEW 조회
SQL> SELECT * FROM DEPT_SAL;
 
SUM(A.SAL)     DEPTNO
---------- ----------
      8750         10
     10875         20
      9400         30

 

 ◈ 위에서 생성한 CREATE MATERIALIZED VIEW 구문을 살펴 보겠습니다.


 - BUILD IMMEDIATE : MView 생성과 동시에 데이터들도 생성되는 옵션입니다.. 

 - BUILD DEFERRED : MView를 생성은 하지만, 그 안의 데이터는 추후에 생성하도록 하는 기능 입니다.
   .위에 MView 생성시 BUILD IMMEDIATE 대신 BUILD DEFERRED 옵션을 사용하면 조회된
     데이터가 없겠죠.. 


 - REFRESH 절은 오라클이 MView의 데이터를 언제, 어떻게 Refresh 하는지를 결정 하는 방법입니다.
   .Refresh 방법에는 ON COMMIT 방법과, ON DEMAND 방법 2 가지가 있습니다.
 
   .ON COMMIT 은 기초 테이블에 Commit 이 일어날 때 Refresh 가 일어나는 방안이며,
    이는 1 개의 테이블에 COUNT(*), SUM(*)과 같은 집합 함수를 사용하거나, MView에 조인만이
    있는 경우,  Group By 절에 사용된 컬럼에 대해 COUNT(col) 함수가 기술된 경우만
    사용이 가능 합니다.
 
   .ON DEMAND는 사용자가 DBMS_MVIEW 패키지 (REFRESH, REFRESH_ALL_MVIEWS,
    REFRESH_DEPENDENT) 를 실행 한 경우 Refresh 되는 경우 입니다.

 
 - Refresh를 하는 방법에는 FORCE, COMPLETE, FAST, NEVER의 4가지가 존재 합니다.

   .COMPLETE : MView의 정의에 따라 MView의 데이터 전체가 Refresh 되는 것으로
                          ATOMIC_REFRESH=TRUE와 COMPLETE으로 설정한 경우 입니다.

   .FAST : 새로운 데이터가 삽입될 때마다 점진적으로 Refresh 되는 방안으로 Direct Path나
                Mview log를 이용 합니다.

   .FORCE : 이 경우 먼저 Fast Refresh가 가능한지 점검 후 가능하면 이를 적용하고,
                  아니면 Complete Refresh를 적용 합니다.(디폴트)

   .NEVER : MView의 Refresh를 발생시키지 않습니다
 
 
 - ENABLE QUERY REWRITE : MView 생성시 이 옵션을 주어야만 임의의 SQL문장을을 처리시
        Query Rewrite를 고려 합니다.
   만일 MView 생성시 이를 지정하지 않은 경우는 ALTER MATERIALIZED VIEW를 이용하여
   수정하면 됩니다.
 
 - 마지막으로 일반 View나 Snapshot처럼 AS 구문 뒤에 필요한 컬럼과 조건들을 기술 하면 됩니다



 <<참고문헌>>
 - Oracle Technical Note Materialized View  글 / 박경희
 - Oracle Technical Bulletins  No.12181 MATERIALIZED VIEW 활용방법
 - Oracle 8i Tuning 정식 교재

반응형

'ORACLE > ADMIN' 카테고리의 다른 글

INSERT /*+ APPEND */ VS CTAS  (0) 2009.02.06
Query Rewrite와 MView Refresh.  (0) 2009.02.05
Materialized View  (0) 2009.02.05
ALTER ~ SHRINK SPACE  (0) 2009.02.05
oracle tablespace 사용량 확인 sql  (0) 2008.12.30
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 5. 14:52
반응형

  Materialized View란 ?

Materialized View(이하 MView로 표시) 이것은 제목 그대로 View 입니다.
 
하지만 일반 View는 논리적인 테이블이고, MView는 물리적으로 존재하는 테이블 입니다.
물리적으로 존재한다는 것은 Data가 일정 공간을 차지하고 있다는 거죠.. 
 
MView는 어떤 결과를 뽑아 내는 쿼리가 너무나도 빈번히 사용 될 경우, Query 실행 시간의 수행속도
향상을위하여 , 여러 가지의 Aggregate View를 두어, 미리 비용이 많이 드는 조인이나,
Aggregate Operation 을 처리하여야 하는 SQL을 위해, 데이터베이스의 한 테이블로 저장 하며,
그 테이블을 조회 하도록 하는 것 입니다.


간단하게 설명하면 대용량의 데이터를 SUM, MIN, MAX, AVG, COUNT(*)이런 명령어를 사용해
너무나도 자주 조회하는 Query를 수행속도를 향상을 위해서,  Query의 결과 만큼의 새로운 테이블을
생성해 놓는 벙법 입니다.

자주사용되는 View의 결과를 디스크에 저장해서 Query 속도를 향상시키는 개념 이죠.

 

Materialized View의 특징

 - MView를 만들어두면 QUERY의 수행속도를 증가 시킬 수 있습니다.

 - SQL 응용프로그램에서 MView 사용시 DBA는 프로그램에 영향을 끼치지 않고 언제든지 생성 및
    제거가 가능 합니다.

 - MView는 실행의 결과 행과 뷰 정의 모두 저장이 되고, 실행 결과 행으로 만들어진 테이블은 일정
   공간을 차지 합니다.

 - MView관련 기초 테이블을 변경하면, MView로 생성된 Summary 테이블도 변경 되어 집니다.

 

Materialized View와 일반 View의 차이점

 - 가장 큰 차이점은 MView의 결과값은 물리적으로 존재하는 것이고,
   일반 View의 결과값은 물리적으로 존재하지 않습니다.

   즉 SELECT * FROM USER_SEGMENTS 하면 MView는 나오지만 일반 View는 나오지 않습니다.

 - MView는 MView를 생성할때의 Query로 물리적으로 이미 데이타가 생성되어 있기 때문에
   조회 속도가 빠릅니다.   
   하지만 View는 단지 쿼리정보가 딕셔너리에 저장되어 있고 사용될때 그 SQL이 다시 실행되는
   것이기 때문에 MView보다 느립니다
.

   MView로 생성된 결과값이 일반 View로 조회하는 Data의 결과값 보다 훨씬 적은 Row를 조회하게 되죠.

 

 MView 관련 파라미터

   - OPTIMIZER_MODE
     MView를 사용하기 위해서는 Cost-Based 옵티마이져 여야 하므로 ALL_ROWS, CHOOSE,
     혹은 FIRST_ROWS 중의 어느 하나를 사용 합니다.
    "CHOOSE"인 상태에서는 모든 테이블을 ANALYZE 시켜 줘야 합니다.

   - QUERY_REWRITE_ENABLED :  Query Rewrite 사용을 위해서는 TRUE로 설정하면 됩니다.

   - QUERY_REWRITE_INTEGRITY : 오라클이 Query Rewrite의 정확성을 제어하는 파라미터로,
     "STALE_TOLERATED", "TRUSTED", "ENFORCED" 로 지정할 수 있습니다.

      STALE_TOLERATED : 사용되어진 기초테이블과 Consistent 하지 않은 View를 이용한
                                      Query Rewrite를 허용 합니다

     TRUSTED : Optimizer에서 MView의 데이터가 정확하다고 간주하고 질의 수행.
                      Integrity 확인을 하지 않습니다.

     ENFORCED: QUERY_REWRITE_INTEGRITY 의 기본값으로, 사용자가 Integrity Constraint를
                       확인하여야 합니다.

   - COMPATIBLE :  사용할 수 있는 오라클 함수들의 Compatibility를 결정하는 값으로 8.1.0 또는
      그 이상으로 설정 해야 합니다.


<<참고문헌>>
 - Oracle Technical Note Materialized View  글 / 박경희
 - Oracle Technical Bulletins  No.12181 MATERIALIZED VIEW 활용방법
 - Oracle 8i Tuning 정식 교재


  ================================================
    * 오라클 정보공유 커뮤니티 oracleclub.com
    * http://www.oracleclub.com
    * http://www.oramaster.net
    * 강좌 작성자 : 김정식 (oramaster _at_ naver.com)
  ================================================
※ oracleclub 강좌를 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
※ oracleclub 강좌는 개인의 학습용으로만 사용 할 수 있습니다. 학원 홍보용이나 수익을 얻기 위한 용도로
    사용을 하시면 안됩니다. ^
반응형

'ORACLE > ADMIN' 카테고리의 다른 글

Query Rewrite와 MView Refresh.  (0) 2009.02.05
MView의 생성  (0) 2009.02.05
ALTER ~ SHRINK SPACE  (0) 2009.02.05
oracle tablespace 사용량 확인 sql  (0) 2008.12.30
Oracle Flashback  (0) 2008.12.18
Posted by [PineTree]
ORACLE/ADMIN2009. 2. 5. 11:25
반응형

ALTER ~ SHRINK SPACE


결론으로부터 말하면 SHRINK에 세그먼트(segment)의 축소(HWM 의 저하)의 효과를 기대한다면 행 이행·행 연쇄를 해소하고 나서 실행하는 편이 좋을 것이다.(행 연쇄는 지울 수 없기 때문 ASSM 에서는 어디에 연쇄할까는 운나름 ???)

 

SHRINK 조작은 Oracle 10g부터의 기능이며 ONLINE에서 실행할 수 있는 등 매우 유용하지만 약점이 도 존재한다. Oracle 10g R1에서 SHRINK에 대한 효과가 상당히 향상되었다고 생각된다. 최신 릴리스에선 이러한 약점도 반드시 해결되어 있을 것이라 생각한다.(Oracle 10g R2 는 미검증)

 

SHRINK 와 MOVE 의 특징


■ ALTER TABLE MOVE 의 동작 이미지는 다이렉트·패스·인서트로 복제, 오리지날을 TRUNCATE TABLE(그리고 메뉴얼 조작으로 색인을 REBUILD).


■ ALTER TABLE SHRINK 는 단편화의 해소를 도모하는 SQL를 사용해 레코드 단위에 위탁하는 DELETE, INSERT 커서 처리라고 하는 느낌이다.

ALTER TABLE SHRINK 와 ALTER TABLE MOVE 의 대표적인 특징

비교 내용 SHRINK MOVE
ONLINE(다른 처리와 병행) 실행할 수 있을까
아니오
·SHRINK 하행 단위에 처리를 완료시키고 있으므로 RX 락으로 OK.
·MOVE 는 색인 구성표 이외에서는 X 락이 필요하게 된다
참고: 표 락의 종류와 상호 관계
행 이행은 해소할까 아니오(입력 데이터에 의존)
·SHRINK는 단편화의 해소하는 프로세스에 있어서 연쇄하고 있는 상태가 일부(운이 좋다면 전부) 해소될 가능성이 있다.⇒ SHRINK 시의 행 이행의 해소에 대해
·MOVE 는 완전한 재구축이므로 행 이행은 모두 해소된다.
하이워타마크는 내려갈까 데이터 분포에 의존
SHRINK는 대량의 행 이행 및 행 연쇄가 방치된 상태에서는 별로 효과를 기대할 수 없다.⇒ SHRINK 시의 세그먼트(segment) 축소에 대해
·MOVE 는 HWM를 저하시킬 수 있다.
작업에 큰 빈영역(데이터 세그먼트)이 필요한가 아니오 실데이터분 이상의 빈영역이 필요
·SHRINK는 처리의 방식이 행 단위로 이동이 행해지기 때문에 불필요.
·MOVE 는 복제와 삭제라고 하는 구조가 되므로 레코드 건수에 비례한 빈영역이 필요.
작업에는 큰 일시표 영역(템프세그먼트)이 필요한가 아니오 네(색인 상태에 의존)
·SHRINK 는 처리의 방식이 행 단위로 이동이 행해지기 위해 불필요.
·MOVE 는 복제와 삭제라고 하는 구조가 되므로 인덱스의 컬럼수와 레코드 건수에 비례한 일시표 영역이 사용된다.
대규모 색인의 메인터넌스가 발생할까 아니오
·SHRINK 하행 단위에 인덱스도 처리되므로 발생하지 않는다.
·MOVE는 ROWID가 모두 변경된다. 테이블에 색인이 존재하는 경우에는 모든 색인의 재구축 (REBUILD)이 필요하다(수동으로 실시할 필요가 있다).

 

 

SHRINK시의 행 이행의 해소에 대해


SHRINK 조작에 의해서 행 이행이 해소하는 일이 있다. 이것은 단편화를 해소할 경우에 행해지는 레코드 데이터의 이동에 의하는 것으로 항상 연쇄한 상태가 해소하는 것은 아니다. 단편화의 해소(행 데이터의 이동)는 물리 ROWID 에 의해서 핸들링 되고 있는 것처럼 보인다. (연쇄행 단편 ROWID 는 사용하지 않는다?? )

 

세그먼트(segment)의 축소, HWM의 저하에 대해


적당한 스크립트를 만들어 동작을 지켜본 결과 (덤프 한 것은 아니고 ROWID를 작업 전후로 트레이스 했다)있던 SHRINK는 물리 ROWID 를 단편화를 해소하기 위한 중요한 값으로 이용하고 있는 것 같다.(행 단편에 있어서의 연쇄행 단편 ROWID는 사용하지 않는것 처럼 보인다. 데이터·딕셔너리에 정보가 존재하지 않을것이다.)
어느 테이블이 연속한 데이터 블록으로 구성되어 있다고 가정했을 경우, 그 테이블에 단편화가 발생하고 있는 경우의 SHRINK 의 동작은 ROWID가 큰 값으로부터 차례로 전방의 빈영역에 채우고 있는 것은 아닐까 생각 할수도 있다.
중 요한 점은 세그먼트(segment)의 선두 근처에서 행 이행(또는 행 연쇄)이 발생하고, 실제의 격납 위치가 세그먼트(segment)의 마지막(HWM)에 가까운 위치에 연쇄하고 있을 때, 그 행 이행이 그대로 남아 버리는 일(※)이 있다고 하는 점이다.
이것은 다른 모든 레코드가 단편화를 해소해 연속한 빈영역이 발생해도 HWM의 행 이행에 의한 데이터 블록의 점유에 의해서 HWM 의 위치를 거의 낮추지 못하는 것을 나타낸다.⇒ 테이블·풀 스캔시에 엑세스 블럭이 많아짐. 

 

(※) Oracle 10g R1 에 대한 실험의 행동으로부터의 예상

 

세그먼트(segment)의 축소 효과가 낮을 때의 SHRINK 의 동작 이미지

 

또 SHRINK 하행 단위로 처리를 행하기 때문에 MOVE 동작과는 달리 자동 세그먼트(segment) 영역 관리에 의한 PCTUSED 에 해당하는 한계치의 영향을 받고 있을 가능성도 생각할 수 있다.(미검증).

이러한 점으로부터 격납 효율과 하이워타마크를 내리는 것에 있어서 MOVE 에 상당한 우위성이 있다고 생각된다.

 

 

SHRINK 실행시의 주의점


사용하기 위한 전제

  • 테이블 영역이 로컬 관리 테이블 영역, 자동 세그먼트(segment) 영역 관리인 것
  • LONG 열을 포함하지 않는 것
  • 클러스터화 테이블이 아닌 것
  • 압축테이블이 아닌 것

세그먼트(segment)의 축소를 할 수 없는 케이스

  • 펑션 색인, 비트 맵 결합 색인을 사용하고 있는 장소
  • ON COMMIT 마테리아라이즈드·뷰의 마스터 테이블의 경우

그외

  • ROWID 가 변경되기 위해 ROWID 마테리아라이즈드·뷰는 재구축 하지 않으면 정합성이 맞지 않게 된다

 

관련사항


 

테이블에 있어서의 SHRINK 의 사용예
행 이행·행 연쇄를 검출한다
SHRINK 가 실행 가능한 schema 테이블(파티션표를 포함한다), 인덱스 구성표(오버플로우를 포함한다), 인덱스LOB 세그먼트(segment), 마테리아라이즈드·뷰(·로그 포함한다)

 

참고사이트 : http://biz.rivus.jp/technote507120.html


반응형

'ORACLE > ADMIN' 카테고리의 다른 글

MView의 생성  (0) 2009.02.05
Materialized View  (0) 2009.02.05
oracle tablespace 사용량 확인 sql  (0) 2008.12.30
Oracle Flashback  (0) 2008.12.18
DICTIONARY(DICT) 뷰  (0) 2008.12.03
Posted by [PineTree]
ORACLE/TUNING2009. 2. 3. 14:53
반응형
Oracle 10g에서 Online Segment Shrink 기능이 추가되면서, 동적으로 Segment의 크기를 줄여 줄 수 있게 되었다. 그러면 다음과 같은 질문을 할 수 있겠다.

"Shrink 대상이 되는 Segment(Table/Index/Partition) 목록을 어떻게 추출할 것인가?"

이런 작업을 수동으로 하려면 dbms_space 패키지를 이용한 일련의 복잡한 Script 작업이 필요하다. Segment 수가 많고 크기가 크다면 많은 시간과 리소스를 필요로 하는 일이 되어 버린다.

다행히 Oracle 10g에서 이러한 작업을 자동화하는 기능이 추가되었다.
아래와 같이 dba_scheduler_job 뷰를 조회해보면, auto_space_advisor_job이라는 스케쥴 작업이 등록되어 있고, 이 작업은 auto_space_advisor_prog이라는 프로그램을 수행한다.

select job_name, program_name
from dba_scheduler_jobs
where job_name like '%SPACE%';
-----------------------------------------------------
JOB_NAME               : AUTO_SPACE_ADVISOR_JOB      
PROGRAM_NAME           : AUTO_SPACE_ADVISOR_PROG

auto_space_advisor 프로그램은 dbms_space.auto_space_advisor_job_proc이라는 프로시저를 수행한다.

select program_name, program_action
from dba_scheduler_programs
where program_name = 'AUTO_SPACE_ADVISOR_PROG';
------------------------------------------------------------
PROGRAM_NAME          : AUTO_SPACE_ADVISOR_PROG   
PROGRAM_ACTION        : dbms_space.auto_space_advisor_job_proc

Auto Space Advisor는 Advisor의 한 종류로 10g에서 새로 추가된 Advisor이다. 이 Advisor는 Tablespace/Segment의 공간 사용 정도를 분석하여 공간을 절약하기 위해 적절한 충고/가이드를 하는 역할을 제공한다.

Auto Space Advisor에 의해 만들어진 가이드는 다음과 같은 방법으로 간편하게 조회 가능하다.

-- dbms_space.verify_shrink_candidate(_tbf) 이용
select * from
table(dbms_space.verify_shrink_candidate_tbf(user,'BIG_TABLE','TABLE',273395165));

declare
    b_shrinkable boolean;
begin
    b_shrinkable := dbms_space.verify_shrink_candidate
        (user,'T_SHRINK','TABLE',1000);
    if b_shrinkable then
        dbms_output.put_line('Shrinkable');
    else
        dbms_output.put_line('Unshrinkable');
    end if;
end;
/

-- dbms_space.asa_recommendations 이용
select * from table(dbms_space.asa_recommendations());

-- dbms_space.asa_recommendations은 다음과 같이 어떤 Segment가 얼마나 공간을 절약할 수 있고, 어떤 명령문을 사용하면 되는지 친절하게 알려준다.
-------------------------------------------------------------
SEGMENT_NAME                  : BIG_TABLE
SEGMENT_TYPE                  : TABLE
ALLOCATED_SPACE               : 300619974
USED_SPACE                    : 273395165
RECLAIMABLE_SPACE             : 27224809
RECOMMENDATIONS               : OWI.BIG_TABLE 테이블의 행 이동을 가능하게 하고 축소 작업을 수행하는 경우 예상되는 절약 공간은 27224809바이트입니다.
C1                            : alter table "OWI"."BIG_TABLE" shrink space
C2                            : alter table "OWI"."BIG_TABLE" shrink space COMPACT
C3                            : alter table "OWI"."BIG_TABLE" enable row movement

Oracle 이 제공하는 Advisor 기능이 점점 다양해지고 정밀해지면서 데이터베이스 진단에 필요한 각종 검증 작업이 대부분 자동화되고 있다. Buffer Cache의 크기나 Shared Pool 크기 진단에서 시작해서 Segment Space 크기 진단으로, 그리고 SQL 성능 자동 진단으로까지 발전하고 있다. Oracle 11g에서는 SQL 성능 진단에서 Index/Materialized View(10g)에 Partition 추천까지 추가될 정도로 이 자동 진단 기능이 확장되고 있다.

아마 이런 자동 진단 및 추천 기능들이 앞으로는 DBA들이 알아야 할 필수 지식이 되지 않을까.

출처 : http://ukja.tistory.com/89
반응형
Posted by [PineTree]
ORACLE/TUNING2009. 2. 3. 14:44
반응형
Oracle 9i에서 Bind Peeking 기능이 소개된 것은 익히 알려진 사실이다.
Bind Peeking이란 Bind 변수를 사용하는 경우, Query가 최초로 실행되는 시점의 실제 Bind 값을 이용해서(Peeking해서) 실행 계획을 세우는 것을 의미한다.

Bind 변수를 사용하는 경우 실제로 실행되는 시점에 어떤 값이 들어오는지 알 수 없기 때문에 컬럼의 평균적인 분포만을 가지고 비용을 계산할 수 밖에 없다. 대부분의 경우에는 큰 문제가 안되지만, 다음과 같은 경우에는 치명적인 단점을 가지고 있다.

가령 status 컬럼의 분포가 다음과 같다고 하면...
 - status = 1  : 99%
 - status = 99 : 1%

이 경우
- Where status = '1' 이면 인덱스를 경유하지 않고 Full Table Scan을 하는 것이 유리하다
- Where status = '99' 이면 인덱스를 경유하는 것이 유리하다.

하지만,
- Where status = :b1 과 같이 Bind 변수를 사용하면 어떤 값이 올지 모르기 때문에 평균적인 분포를 따르게 된다. 따라서 이 경우 반드시 Full Table Scan을 선택한다.

Bind Peeking은 이러한 단점을 피하기 위해 쿼리가 실행되는 최초 시점에 Bind 변수에 들어온 값을 이용하게 된다. 즉, 쿼리가 최초로 실행되는 시점에

exec :b1 := '1';
... Where status = :b1

과 같이 실행되면 Full Table Scan을,

exec :b2 := '99';
... Where status = :b1

과 같이 실행되면 Index Range scan을 선택하게 된다.
단, 위와 같이 작동하려면 컬럼 값이 "1" 인 경우와 "99"인 경우의 분포도의 차이를 Oracle이 명확하게 이해하고 있어야 되므로 Histogram이 반드시 존재해야 한다. 가령

exec dbms_stats.gather_table_stats(user, 'TABLE_NAME', method_opt=>'for columns size 2 status');

와 같이 컬럼에 대해 적당한 크기의 Histogram이 생성되어 있어야 된다.

위의 설명을 이해했다면 Bind Peeking에는 기본적인 딜레마가 있음을 알 수 있다. 위의 예를 보면 쿼리가 최초로 실행되는 시점에 "1"의 값이 오느냐, "99"의 값이 오느냐에 따라 실행 계획이 결정된다. 어떤 쪽이든 한 쪽은 손해를 볼 수 밖에 없는 결정적인 구조적 한계를 가지고 있다.

이런 구조적 한계를 가진 기능을 제공한다는 것은 기본적인 설계의 결함이라고 할 수 있다. 덕분에 많은 시스템에서 Bind Peeking 기능을 비활성화시켜 버리고 있다. _optim_peek_user_binds 파라미터 값을 false로 지정해 버리는 것이다.

이런 경향은 10g에서 특히 심한데, 그 이유는 10g에서 dbms_stats의 method_opt 파라미터의 기본값이 for all columns size auto로 바뀌는 바람에 Histogram의 생성 여부를 Oracle이 자동으로 판단해버리는데 있다. 이전 버전에서는 for all columns size 1 이 기본값으로 Histogram이 생성되지 않았다.
Histogram이 없으면 Bind Peeking에 의한 부작용은 거의 없다. 10g에서 Histogram의 생성 여부를 Oracle이 판단함으로써 이전 버전에서는 존재하지 않던 Histogram이 갑자기 생성되고 이로 인해 Bind Peeking의 결함이 더욱 두드러지게 나타나게 되어 버린 것이다.
이 때문에 Oracle 10g에서는 _optim_peek_user_binds 파라미터를 False로 바꾸는 것이 기본 권고안처럼 되어 버릴 정도가 되었다.

하지만, Oracle 11g에서 아주 큰 희소식이 전달되었다. 이른바 Adaptive Cursor Sharing이라는 기능이 소개된 것인데, 이 기능으로 인해 Bind Peeking과 Histogram의 조합에 의한 부작용이 말끔히 해소될 수 있다.

Adaptive Cursor Sharing이란 말 그대로 상황에 맞게 유연하게 Cursor를 Share하겠다는 의미이다. 이 개념을 구현하기 위해 Oracle은 Bind Sensitive Cursor, Bind Aware Cursor라는 새로운 개념을 도입했다.
Bind Sensitive Cursor란, 말 그대로 Bind 값에 민감한 Cursor라는 의미이다. 즉, Bind 값이 바뀌면 그것을 민감하게 처리하겠다는 의미이다. 1) Equal 조건에서는 조건절에 쓰인 컬럼에 Histogram이 있고 2) Range 조건인 경우 Oracle은 이것을 Bind Senstive Cursor라고 부른다.
Bind Aware Cursor란, Bind Sensitive Cursor에 입력된 Bind 값에 따라 실행 계획이 분화된 Cursor를 의미한다. 즉, Bind Aware Cursor가 생성되었다는 것은 Bind 변수의 값에 따라 Oracle이 적절한 Child Cursor를 생성했다는 것을 의미한다.

Adaptive Cursor Sharing 기법을 사용하면 Bind Peeking에 의해 최초 실행 시점에 실행 계획이 결정되더라도 이후 새로운 Bind 변수 값이 사용되면 이에 맞게 실행 계획을 분화(새로운 Child Cursor 생성)시킨다. 따라서 Bind Peeking에 의한 부작용이 사실상 없어지게 된다.
단, 조건절에 쓰인 컬럼에 Histogram이 있고, Histogram의 분포도에 따라 실행 계획에 큰 차이가 있을 수 있다고 판단된다는 조건이 중요하다. 즉, 적절한 Histogram 없이는 의미가 없다는 것이다. Histogram은 이제 우리가 반드시 이해하고 활용해야 하는 존재가 되었다.
(dbms_stats의 method_opt 파라미터의 기본값이 for all columns size auto로 바뀌는 순간 이미 Histogram은 피할 수 없는 존재가 되어버렸다는 사실을 기억할 필요가 있겠다)

아래 샘플 코드를 이용하면 Oracle 11g의 Adaptive Cursor Sharing 기법을 이해할 수 있다.

-------------------------------------
-- Oracle 11g Bind Aware Cursor
-- Author: 조동욱
--------------------------------------

-- create objects
drop table acs_table;

create table acs_table(id int, name char(10));

create index acs_table_idx on acs_table(id);

insert into acs_table select 1, 'name' from all_objects where rownum <= 100000

insert into acs_table values(99, 'name');

commit;

-- gather statistics with histogram
exec dbms_stats.gather_table_stats(user, 'ACS_TABLE', estimate_percent=>100, method_opt=>'FOR COLUMNS SIZE 2 ID', cascade=>true);

-- check histogram
select * from dba_tab_histograms where table_name = 'ACS_TABLE';

-- Bind query
alter system flush shared_pool

var id number;

-- id == 1
-- 각 단계마다 아래 쿼리 결과 확인
select sql_id, sql_text,is_bind_sensitive,is_bind_aware
from v$sql where sql_text like 'select count(name) from acs_table%';

exec :id := 1;

select count(name) from acs_table where id = :id;

-- id == 99
exec :id := 99;

select count(name) from acs_table where id = :id;

select count(name) from acs_table where id = :id;

-- id == 1 again
exec :id := 1;

select count(name) from acs_table where id = :id;

-- check mismatch
select * from v$sql_shared_cursor where sql_id = '<sql_id>';

Oracle 11g의 Adaptive Cursor Sharing은 Oracle이 Bind 변수와 Histogram의 기능 개선에 얼마나 노력을 기울이고 있는지를 잘 보여주는 단적인 예이다. 아마 기대컨데, 더 이상 Bind Peeking의 부작용에 대해 고민하지 않아도 되기를 기대해본다.

출처 : http://ukja.tistory.com/87


반응형

'ORACLE > TUNING' 카테고리의 다른 글

Nested Loop Join과 Sort Merge Join  (0) 2009.02.06
Oracle 10g에서 Shrink 대상 Segment 찾기  (0) 2009.02.03
오라클 hint 사용법  (2) 2008.11.24
Transaction internals  (0) 2008.11.11
옵티마이저의 비용계산 방법과 실행원리  (0) 2008.11.07
Posted by [PineTree]
ORACLE/SQL2009. 1. 22. 20:57
반응형


◎ SQL PLUS상에서 STORED PROCEDURE 소스 확인 방법



USER_SOURCE 데이터 사전을 이용하면 됩니다.
 
  -- USER_SOURCE의 구조를 살펴보면
  SQL>
DESC USER_SOURCE
   
        이름            유형
------------- ------------------
        NAME          VARCHAR2(30)
        TYPE          VARCHAR2(12)
        LINE            NUMBER
        TEXT          VARCHAR2(4000)
 
 -
NAME : procedure, function, package의 이름을 가지고 있습니다.
 -
TYPE :  function, package, package body, procedure인지 알수 있습니다.
 -
LINE : function, package, package body, procedure의 라인을 보여줍니다.
 -
TEXT : function, package, package body, procedure의 소스를 알 수 있습니다.
 


 
-- 어떤 프로시져들이 존재하는지 확인 
SQL> SELECT DISTINCT
(name) FROM USER_SOURCE WHERE TYPE = ’PROCEDURE’;
 
NAME
------------------------------
FORCURSOR_TEST
IMPLICIT_CURSOR
 




-- 프로시져 소스의 확인
SQL> SELECT
text FROM USER_SOURCE WHERE name=’FORCURSOR_TEST’;

 -- 쿼리 결과
     PROCEDURE ForCursor_Test
        IS

        CURSOR dept_sum IS
        SELECT b.dname, COUNT(a.empno) cnt, SUM(a.sal) salary
        FROM emp a, dept b
        WHERE a.deptno = b.deptno
        GROUP BY b.dname;
     BEGIN
       -- Cursor를 FOR문에서 실행시킨다
       FOR emp_list IN dept_sum LOOP
          DBMS_OUTPUT.PUT_LINE(’부서명 : ’ || emp_list.dname);
          DBMS_OUTPUT.PUT_LINE(’사원수 : ’ || emp_list.cnt);
          DBMS_OUTPUT.PUT_LINE(’급여합계 : ’ || emp_list.salary);
       END LOOP;
   EXCEPTION
       WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE(SQLERRM||’에러 발생 ’);
   END;
 
18 개의 행이 선택되었습니다.


  ================================================
    * 오라클 정보공유 커뮤니티 oracleclub.com
    * http://www.oracleclub.com
    * http://www.oramaster.net
    * 강좌 작성자 : 김정식 (oramaster _at_ naver.com)
  ================================================
반응형
Posted by [PineTree]