oracle index rebuild를 판단하는 기준이나 rebuild가 필요한지 자체에 대한 많은 말들이 있긴한데.. 

다음의 글은 index_stats view의 del_lf_rows를 이용한 index rebuild 방안에 대한 구조적인 한계에 대한 설명입니다.
뭐 이러한 방안을 대량 delete 작업 후 바로 적용하면 될 거 같은데,
아래와 같은 내용을 알아둬야 .. 수치가 좀 이상하게 나올 경우 당황하지 않겠네요~ 

But, as the Oracle myth busters like Richard Foote have been saying for years,  that's not how Oracle's B-tree indexes work. When you delete an index entry, Oracle marks it as deleted but leaves it in place. When you commit your transaction Oracle does nothing to the index entry – but other processes now know that the entry can be wiped from the block allowing the space to be re-used.      (원문 : Index Rebuilds « Oracle Scratchpad )




데이터 파일의 저장공간을 넉넉히 갖고 운영할 수 있으면 좋겠지만, 대부분의 사이트 들은 한정된 disk 공간으로 운영을 합니다.  Disk의 가격도 만만치 않거니와 향후 발생할 데이터 양을 너무 빡빡하게 계산해 놓으면 이 한정된 disk를 알뜰하게 DBA들이 사용해야 하죠. 

Disk의 공간을 줄이기 위해 compress table이나 table re-org 작업, tablespace shrink 작업들을 하게되는데 오늘은 Bulletin 10165의 내용을 정리합니다. 

tablespace shrink 작업은 extent가 할당되지 않은 공간 중 마지막 extent 부분 부터 줄일 수 있습니다. 즉, tablespace가 처음 할당 되고 얼마 되지 않은 table 들이 생성됬을 경우 꽤 짭짭할 공간을 줄일 수 있겠지만, 이미 사용한지 좀 된 tablespace의 경우에는 중간중간 extent가 할당되어 얼마 못 줄이게 됩니다. 이런 경우에는 table을 drop하고 재 생성하는 등의 re-org 작업이 선행 되거나 tablespace를 이리저리 건너 뛰면서 줄여야 됩니다. 

그럼 tablespace를 resize 할 수 있는 max size를 어떻게 구할 수 있을까요? 

dba_extents라는 view를 보면 datafile 별로 extent가 할당된 정보가 나옵니다. 이 할당된 extent의 마지막 위치를 파악해서 바로 그 이후로 size를 지정하면 됩니다.  다음의 공식은 bulletin 10165에 나와 있는 공식입니다. 

1) 줄이고자하는 file id를 확인합니다.
SQLPLUS> select file_id, file_name from dba_data_files;

2) 얼마를 사용했는지 확인합니다.
SQLPLUS> select block_id, blocks from dba_extents where file_id='FILE_ID' order by block_id;

FILE_ID 대신에 줄이려는 file id를 기술합니다.

3)현재 사용중이 db block size를 확인합니다.
SQLPLUS> show parameter db_block_size

2)에서 조회된 마지막의 block_id, blocks 값을 가지고 계산합니다. 
block_id * db_block_size + blocks * db_block_size 의 결과에 한 block더한 값만큼만 줄이는 것이 가능합니다. 

만일 마지막으로 조회된 값이 block_id가 578261, blocks가 515, db_block_size가 2048 일 경우  
578261*2048 + 515*2048 =1185333248로 최소한 1.2GB이상은 써야 합니다. 

4) 실제 datafile을 줄입니다.
SQLPLUS>alter database datafile '/oracle/dbs/toolsORA.dbf' resize 1200M;



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



Oracle 관련된 전문 블로거들의 RSS를 구독하고 있습니다. 
좀 흥미로운 내용이 있어 소개해 드립니다. 

Did you know that it’s possible to use EXPLAIN PLAN FOR CREATE INDEX ON table(col1,col2,col3) syntax for explaining what exactly would be done when an index is created?

That’s useful for example for seeing the Oracle’s estimated index size without having to actually create the index.

You can also use EXPLAIN PLAN FOR ALTER INDEX i REBUILD to see whether this operation would use a FULL TABLE SCAN or a FAST FULL INDEX SCAN (offline index rebuilds of valid indexes can use this method).


위의 내용은 읽어 보시면 아시겠지만, EXPLAIN PLAN FOR 명령을 이용해 생성할 INDEX의 size를 추측해 보는 방법을 설명하고 있습니다. 
EXPLAIN PLAN FOR는 일반적으로 수행행되는 SQL의 PLAN이나 statistic 값들을 확인하기 위해 사용되는데, 
해당 SQL이 수행되면서 읽을 양으로 INDEX size를 판단할 수 있다는 내용입니다. 

위 포스트에서 설명한 내용을 그대로 한번 따라가 보겠습니다. 

SQL> show user
USER is "SCOTT"
SQL> explain plan set statement_id = 'cr_emp_idx01' for  create index emp_idx01 on emp(empno);   

Explained.

SQL> @?/rdbms/admin/utlxpls

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 188079254

------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | CREATE INDEX STATEMENT |           |    14 |    56 |    13   (0)| 00:00:01 |
|   1 |  INDEX BUILD NON UNIQUE| EMP_IDX01 |       |       |            |          |
|   2 |   SORT CREATE INDEX    |           |    14 |    56 |            |          |
|   3 |    TABLE ACCESS FULL   | EMP       |    14 |    56 |    12   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Note
-----
   - estimated index size: 65536  bytes

14 rows selected.

위의 plan 결과에 따르면 해당 index는 65536 bytes가 되겠군요.
그럼 INDEX를 한번 만들어 보겠습니다.

SQL> create index emp_idx01 on emp(empno);

Index created.

SQL> column segment_name format a30
SQL> column segment_type format a30
SQL> select segment_name,segment_type,bytes from user_segments where segment_name= 'EMP_IDX01';

SEGMENT_NAME                   SEGMENT_TYPE                        BYTES
------------------------------ ------------------------------ ----------
EMP_IDX01                      INDEX                             1048576

SQL>  

SQL> connect system/manager
Connected.

SQL> select segment_name,segment_type,tablespace_name from dba_segments where segment_name = 'EMP_IDX01'; 

SEGMENT_NAME                   SEGMENT_TYPE                   TABLESPACE
------------------------------ ------------------------------ ----------
EMP_IDX01                      INDEX                          TS_TEST01


SQL> column tablespace_name format a10
SQL> select TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT from dba_tablespaces where tablespace_name = 'TS_TEST01';

TABLESPACE INITIAL_EXTENT NEXT_EXTENT
---------- -------------- -----------
TS_TEST01         1048576     1048576

EMP_IDX01이 저장될 tablespace의 initial extent 값이 1048576이라
INDEX size 65536 bytes는 한개의 extent에 모두 저장되었군요.

PLAN에서 보여준 statistic 값은 Block scan 결과만 보여주는 것이니 PCTFREE 등의 값의 영향으로 약간의 가감은 필요할 것 같습니다만.
대충 얼마정도의 공간이 필요할 것이다라는 것에 대한 힌트는 될 것 같습니다.



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!





Oracle 11g에서 많은 새로운 기능들이 생겼습니다.
그러나 oracle 11g를 설치하면 제일 먼저 눈에 띄는게 OFA 구조가 바뀐거죠. 
(설치 후 alert log를 한참동안 찾아 헤메였다는.. ^^;)

전통적으로 oracle alert log file과 trace file들은 $ORACLE_BASE/admin/$ORACLE_SID/bdump 에 쌓였었죠. 
(아마 8.0 때부터였던가.. 그랬었을 겁니다. 아마 ㅋ)
가끔 bug이나 resource 문제로 $ORACLE_HOME/rdbms/log에 생기기도 했고요. 

Oracle 11g에서는 이 구조가 좀 바뀌었습니다. $ORACLE_BASE 밑에 diag란 directory 밑에 쪼르륵 달려있습니다. 

$ORACLE_BASE/diag/rdbms/'DATABASE NAME'/$ORACLE_SID/trace

이렇게 구조가 달라진 이유는 아마 metalink.oracle.com에서 support.oracle.com으로의 변화와 OCM (oracle configuration management) 때문이지 않을까 싶습니다. 즉, database의 특정 환경, event 들을 OCM을 통해 support.oracle.com에서 지원하려는 .. 뭐 그런 이유 이지 않을까 싶습니다. 

암튼 단순히 trace file과 alert log의 위치만 변경된 것은 아니죠. adrci라는 diag file 관리 tool이 만들어 졌습니다. 
이 tool을 이용해 현재 발생한 problem, incident 등을 쉽게 파악할 수 있으며, 기간이 오래된 trace file 등을 한방에 정리도 할 수 있습니다.
이러한 기능은 EM에서도 가능하고요. 

oracle 내에서 어떤 문제가 생겨 SR을 open해 분석을 진행할때 가장 귀찮은 게 관련 trace, log file을 취합해서 upload하는 겁니다. (저는 그래요.. ㅋ) adrci에서는 관련 trace, log file을 한꺼번에 취합해 주는 기능이 있는데, 이것이 IPS (incident packaging service) 입니다. 

구조가 바뀌고 "PROBLEM"과 "INCIDENT"라는 단어들이 나오는데, Problem은 특정한 문제 전체를, Incident는 문제의 발생 자체를 말합니다. 즉, ORA-1555가 10번 발생했다면 ORA-1555 1개의 문제에 10번의 incident가 발생한게 됩니다.

다음은 ADRCI에서 incident를 packaging 하는 방법입니다. 
그냥 보시면 아실만한 내용이라 별도의 설명은 생략하겠습니다. 

$ adrci

ADRCI: Release 11.1.0.7.0 - Production on Mon Mar 8 16:35:56 2010

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

ADR base = "/oracle"
adrci> 
adrci> show incident

ADR Home = /oracle/diag/rdbms/test/TEST01:
*************************************************************************
INCIDENT_ID          PROBLEM_KEY                                                 CREATE_TIME                              
-------------------- ----------------------------------------------------------- ---------------------------------------- 
656910               ORA 600 [critical problem임]                                2010-01-29 11:31:45.635899 +09:00       
656909               ORA 600 [critical problem임]                                2010-01-29 11:19:30.662164 +09:00       
656478               ORA 7445 [critical problem임]                               2010-01-25 13:21:00.086171 +09:00       
656477               ORA 7445 [critical problem임]                               2010-01-25 13:16:54.434050 +09:00       
               ...
20 rows fetched

ADR Home = /oracle/diag/clients/user_oracle/host_2085451943_11:
*************************************************************************
INCIDENT_ID          PROBLEM_KEY                                                 CREATE_TIME                              
-------------------- ----------------------------------------------------------- ---------------------------------------- 
25                   oci 24550 [3]                                               2009-08-19 17:01:14.504278 +09:00       
17                   oci 24550 [3]                                               2009-08-19 16:59:56.250301 +09:00       
9                    oci 24550 [3]                                               2009-06-18 08:09:28.329766 +09:00       
1                    oci 24550 [3]                                               2009-06-18 08:07:58.791738 +09:00       
4 rows fetched

adrci> show homepath
ADR Homes: 
diag/rdbms/test/TEST01
diag/clients/user_oracle/host_2085451943_11
diag/clients/user_precise/host_2085451943_11
diag/clients/user_norad/host_2085451943_11
diag/tnslsnr/TEST01/test_TEST01
diag/tnslsnr/TEST01/listener_TEST01
diag/tnslsnr/TEST01/listener_TEST01
diag/tnslsnr/TEST01/listener
adrci> set homepath diag/rdbms/test/TEST01
adrci> ips create package incident 656910
Created package 1 based on incident id 656910, correlation level typical
adrci>
adrci> IPS GENERATE PACKAGE 1 in /oracle/diag
Generated package 1 in file /oracle/diag/ORA600critical problem임_20100308163713_COM_1.zip, mode complete
adrci> exit
$ls -altr
total 12744
-rw-r--r--   1 oracle     dba        6456404 Mar  8 16:39 ORA600critical problem임_20100308163713_COM_1.zip

참고: 
Note.738732.1 ADR How to Package Diagnostic Information in 11g





Oracle global temporary table은 Transaction 내에서 임시로 만들 수 있는 table을 지칭합니다. 
transaction 내부에서 사용하는 것이니 당연히 transaction을 commit/ rollback하면 없어지겠죠. 

"global"이라는 단어가 붙은 이유는 table의 구조는 공유한데서 나오니 않았나 싶습니다. 
같은 global temporary table에 각각의 세션에서 데이터를 insert 하면 서로 다른 값을 보여주게 됩니다. 

Global temporary table 생성 명령은 table 생성명령에 global temporary 만 넣어주면 됩니다. 

create global temporary table test_temp ..

global temporary table을 만든 후 dba_objects에서 query를 해보면 해당 이름으로 object_type이 table이라고 나오긴하나, 
dba_segments에서는 해당 이름의 segment는 없는 것으로 보여줍니다. v$sort_usage를 보니 temp tablespace에 temporary data segment type으로 한덩어리 만들어 놓았군요..






Oracle External table은 오라클 외부의 데이터를 내부로 loading해 table 형식으로 보여 줍니다.
Oracle 11g R2에서는 "PREPROCESSOR 절"이 생겨 이 외부 file에 대해 선처리 프로세서를 정의해 줄 수 있습니다.

대부분 외부 SAM file 형식이니 압축해제나 shell을 통한 추출 정도의 선 프로세서를 정의할 수 있겠네요.
잘만 된다면 SAM file 저장하는 공간을 줄일 수 있겠네요.

예 : compress된 데이터를 gunzip을 이용해 압축 해제 후 loading

CREATE TABLE sales_transactions_ext
     (PROD_ID NUMBER, CUST_ID NUMBER, TIME_ID DATE, CHANNEL_ID NUMBER, PROMO_ID NUMBER, QUANTITY_SOLD NUMBER,
      AMOUNT_SOLD NUMBER(10,2), UNIT_COST NUMBER(10,2), UNIT_PRICE NUMBER(10,2))
ORGANIZATION external
 (TYPE oracle_loader DEFAULT DIRECTORY data_file_dir
  ACCESS PARAMETERS
  (RECORDS DELIMITED BY NEWLINE CHARACTERSET US7ASCII
   PREPROCESSOR exec_file_dir:'gunzip' OPTIONS '-c'
   BADFILE log_file_dir:'sh_sales.bad_xt'
   LOGFILE log_file_dir:'sh_sales.log_xt'
   FIELDS TERMINATED BY "|"
   LDRTRIM ( PROD_ID, CUST_ID, TIME_ID DATE(10) "YYYY-MM-DD", CHANNEL_ID, PROMO_ID, QUANTITY_SOLD,
                AMOUNT_SOLD, UNIT_COST, UNIT_PRICE))
location ('sh_sales.dat.gz') )
REJECT LIMIT UNLIMITED;






1.
1. Shutdown the database
2. Move the datafile to its new location.
3. Do a "STARTUP MOUNT"
4. ALTER DATABASE RENAME FILE '/old/location' TO '/new/location';
5. ALTER DATABASE OPEN;


2.
--Create new undo tablespace:
SQL> create undo tablespace UNDOTBS02 datafile '/u03/app/oracle/oradata/ovpi/undo02.dbf' size 1000m;

--Set new tablespace as undo_tablespace:
SQL> alter system set undo_tablespace=undotbs02;

--Drop the old tablespace:
SQL> drop tablespace undotbs including contents;

When dropping the old tablespace, you may encounter an ORA-30013 error.
This essentially indicates that you must wait for any existing transactions using this tablespace to either commit or rollback before the tablespace can be dropped.

그럼 undo_retention 까지 기다려야 할까?
아니면 undo_retention은 무시되며 drop 될까?  아마 drop 되지 않을까.. 싶다..

http://www.orafaq.com/forum/t/63723/2/






다음은 oracle korea에서 만든(?) oracle 9i의 new feature인 data block prefetching에 대한 내용을 발췌했습니다..

데이타 블럭 프리페칭(Data Block prefetching)은 Oracle9i에서 새롭게 선보이는 내부 최적화 기능으로서 특정한 경우에 질의 응답 시간을 크게 개선할 수 있다. 데이타 블럭 프리페칭은 테이블 조회(lookup)에 의해 사용된다.

색인 액세스 경로가 선택되고 질의가 색인 만으로는 충족될 수 없을 경우, rowid가 지시하는 데이타 행 역시 페치되어야 한다. 이 데이타 행 액세스(테이블 조회)에 대한 rowid는 올바른 rowid의 어레이가 지시히는 블럭 어레이를 읽는 것을 수반하는 데이타 블럭 프리페칭을 사용해 개선됐다.

블럭 프리페칭은 I/O 처리 성능에 대한 보다 효과적인 활용과 가능할 경우 항상 병렬 읽기를 발행해 응답시간을 단축시킬 수 있도록 지원한다.

데이타 블럭 프리페칭은 대개 색인이 빈약하게 클러스터링되고 테이블 액세스가 전반적으로 낮은 버퍼 캐시 적중률 의 랜덤 디스크 액세스를 수반하는 경우 유용하다.

이 경우 질의는 시스템 상에 가용 I/O 대역폭이 있더라도 이들 단일 블록 들이 캐시로 동시에 읽혀지기를 기다림으로써 손쉽게 I/O 최대값에 도달할 수 있다. 데이타 블럭 프리페칭 주요 색인에 만족스러운 rowid의 수가 축적될 때까지 테이블 블럭의 읽기를 지연시킨다. I/O 완료 시 훨씬 짧게 기다림으로써 데이타베이스 인스턴스가 CPU 자원을 보다 효과적으로  활용할 수 있도록 지 원하게 된다.



샘플 문제:
TPC-H 스펙의 질의 17은 데이타 블럭 프리페치가 사용될 수 있는 대표적인 예제이다.
해당 브랜드 및 컨테이너 유형의 경우, 평균 보다 20% 적은 수량의 주문이 접수된다면, 연평균 매출액 중 총손실액은 어느 정도인가?

데이타베이스는 7년 간의 데이타를 포함하고 있다.

구현:

다음 질의는(DOP 16) Oracle8i and Oracle9i 모두에서 위의 문제를 구현하는데 사용된다

select  sum(l_extendedprice) / 7.0 as avg_yearly parts,
from   parts,  lineitem l1
where  p_partkey = l_partkey
and p_brand = 'Brand#23'
and p_container = 'MED BOX'
and l_quantity <(
                           select 0.2 * avg(l_quantity)
                           from lineitem l2
                           where l_partkey = p_partkey);

Oracle8i에서 질의 수행시간은 264초였다
Oracle9i에서 질의 수행시간은 180초였으며 이는 31.82%의 향상을 나타낸다


다음은 위의 white-paper의 원문입니다.
영어는 잼병이지만, 아래의 원문을 보기전까지는 위의 말이 뭔소린지 이해가 안됬다능..
(한글 공부를 다시해야 하나 .. 고민)

Data block prefetching is an example of an 'under the covers' performance feature provided in Oracle9i. This feature is entirely transparent to both the end-users and database administrator, yet it can improve performance by 30% or more for individual queries.

Data block prefetching can significantly improve the performance of queries which retrieve large numbers of rows via a b-tree index.Data block prefetching provides the largest performance gains for queries which use an index that is 'poorly clustered'. (An index is said to be 'clustered' if the data in the underlying table is in the same order as the index keys. A poorly clustered index is one in which the rows in the underlying table are in an entirely different order than the index keys).

Poorly clustered indexes are quite common, since most tables can only have at most one well-clustered index. Previously, accessing a large number of rows using a poorly clustered b-tree index could be expensive. Each row accessed by the index would likely be in a separate data block and thus would require a separate I/O operation.

The buffer cache is ineffective for these queries because the I/Os are spread throughout the table, and the buffer cache hit ratio is low.

In such cases, a query can easily become I/O bound, waiting for single data blocks to be read into the cache one at a time, even though there may be available I/O bandwidth on the system. With data block prefetching, Oracle delays data blocks reads until multiple rows specified by the underlying index are ready to be accessed and then retrieves multiple data blocks at once, rather than reading a single data block at a time.
Block prefetching allows better utilization of the I/O capacity, and provides a further reduction in response time by issuing I/O operations in parallel whenever possible.


요약하자면 index scan 사용할때 내부적으로 수행되는 기능으로 요구되는 rowid에 의한 access를 일정 block이 될때까지 기다려 한꺼번에 수행하는 기능 입니다.

With data block prefetching, Oracle delays data blocks reads until multiple rows specified by the underlying index are ready to be accessed and then retrieves multiple data blocks at once, rather than reading a single data block at a time.






BFT (BigFileTablespace)는 oracle 10g에서 사용가능한 tablespace type 이다. Bigfile Tablespace는 하나의 매우 큰 datafile을 갖는 tablespace를 말한다. Bigfile tablespace의 개념이 만들어 지면서 기존의 일반적인 tablespace는 자동으로 smallfile tablespace로 불린다.

SMALLFILE tablespace와 BIGFILE tablespace는 database내에 공존할 수 있다.

      SQL> select TABLESPACE_NAME, BIGFILE from DBA_TABLESPACES;

      TABLESPACE_NAME                BIG
      ------------------------------ ---
      SYSTEM                         NO
      UNDOTBS1                       NO
      SYSAUX                         NO
      TEMP                           NO
      USERS                          NO
      TEST_BIG                       YES

BIGFILE tablespace는 하나의 datafile만을 사용하게 된다. 이는 datafile에 대한 관리가 간편해 질 수 있다는 것을 의미하며, 일반적인 SMALLFILE tablespace에서 사용하던 다음과 같은 option도 역시 사용가능하다.

      SQL> ALTER TABLESPACE test_big AUTOEXTEND OFF;
      Tablespace altered.

      SQL>  ALTER TABLESPACE test_big AUTOEXTEND ON;
      Tablespace altered.

      SQL> ALTER TABLESPACE test_big RESIZE 2M;
      Tablespace altered.

BIGFILE tablespace는 다음과 같이 사용될 수 있다.

      --> ASM (Automatic Storage Management)
      --> a logical volume manager supporting striping/RAID
      --> dynamically extensible logical volumes
      --> Oracle Managed Files (OMF)

만약 default로 BIGFILE tablespace를 생성하고 싶다면 다음과 같이 tablespace 생성 option을 바꿀 수 있다.

    SQL> select * from database_properties
          where property_name='DEFAULT_TBS_TYPE';

     PROPERTY_NAME        PROPERTY_VALUE  DESCRIPTION
     -------------------- --------------- ------------------------
     DEFAULT_TBS_TYPE     SMALLFILE       Default tablespace type
   
     SQL> ALTER DATABASE SET DEFAULT bigfile TABLESPACE;
     Database altered.

     SQL> CREATE TABLESPACE big_test2
          DATAFILE '/ORACLE10/ORCL/testbig2.dbf' size 1M;

     Tablespace created.

     SQL> select TABLESPACE_NAME, BIGFILE from DBA_TABLESPACES;

     TABLESPACE_NAME                BIG
     ------------------------------ ---------
     ...
     USERS                          NO
     TEST_BIG                       YES
     TEST_BIG2                      YES

앞서 말한 것 처럼 BIGFILE tablespace에는 datafile 추가는 불가능하다.

      SQL> ALTER TABLESPACE test_big
           ADD DATAFILE '/ORACLE10/ORCL/testbig2.dbf' size 500G;

      ALTER TABLESPACE test_big
      *
      ERROR at line 1:
      ORA-32771: cannot add file to bigfile tablespace


여러 datafile을 사용해 큰 공간을 확보하는 방법에 비해 하나의 큰 파일로 tablespace를 구성하는 이 방법은 관리상의 이점이 있으나, backup이나 recovery 단계에서는 큰 file에 대한 backup과 file 손상이 발생할 경우 전체를 restore해야 하기 때문에 오히려 부담이 될 수 도 있다. 따라서 각각의 tablespace type에 대한 이점과 단점을 구분하고 적용해야할 것이다.

참고 문서 :
Note 262472.1  10g: BIGFILE Type Tablespaces Versus SMALLFILE Type
Note 243245.1  10G New Storage Features and Enhancements
Note 1057891.6 HOW TO USE DBMS_ROWID PROCEDURE AND FUNCTIONS








Block split은 새로운 index key가 들어왔을때 기존에 할당된 block내에 저장할 영역이 없어 새로운 block을 할당 받는 index segment관련 operation 입니다.

Index Block Split은 새로 들어오는 index key 데이터에 따라 2개의 다른 방식으로 이루어 집니다.


1. index key 값이 기존의 index key 값에 비해 제일 큰 값이 아닐 경우 50/50  
   block split이 발생한다. 50/50 split은 기존에 존재하던 old block과 새로
   만들어진 new block에 50%의 데이터씩 채워져 split이 발생하게 된다.

2. index key 값이 기존의 index key 값에 비해 제일 큰값이 들어올 경우 99/1
   block split 이 발생한다. 99/1 split은 기존에 존재하던 old block에 99%의
   데이터가 있고 new block엔 새로운 데이터가 저장되게 된다.

이러한 index key의 저장 영역의 확인은 "analyze .. validate structure" 수행 후 index_stats view의 조회를 통해 확인 할 수 있습니다.

다음의 예는 간단한 테스트 입니다.

1. 계속 증가되는 데이터에 의해 99/1 split이 발생하는 예제 입니다.

SQL> drop table t1;
SQL> create table t1 (name varchar2(10),nr number) pctfree 0;
SQL> create index i1 on t1(nr);
SQL> declare
     i number;
     begin
     for i in 1..50000
     loop
     insert into t1 values('XX',i);
     end loop;
     end;
/

SQL> analyze index i1 validate structure;
SQL> select blocks, lf_blks, pct_used from index_stats;

Results:

BLOCKS: 104 LF_BLKS: 99 PCT_USED: 99


2. 데이터의 입력 순서를 바꿔 50/50 split이 발생하는 예제입니다.

SQL> drop table t2;
SQL> create table t2 (name varchar2(10),nr number) pctfree 0;
SQL> create index i2 on t2(nr);
SQL> declare
     i number;
     begin
     for i in 25000..50000
     loop
      insert into t2 values('XX',i);
     end loop;
     for i in 1..25000
     loop
      insert into t2 values('XX',i);
     end loop;
     end;
/

SQL> analyze index i2 validate structure;
SQL> select blocks, lf_blks, pct_used from index_stats;

Results:

BLOCKS: 256 LF_BLKS: 146 PCT_USED: 68

마지막의 blocks의 결과를 보시면 데이터의 입력 순서에 따라 데이터의 저장영역이 2배 이상 차이가 나는 것을 확인 할 수 있습니다.

이거 보시고 99/1로 index split을 하면 저장역역을 아낄 수 있겠지만,
예제1의 t1이 OLTP에서 여러 세션에 의해 insert 되는 table의 index라면
t1에 대한 insert 세션들이 index split을 기다리는 "
enq: TX - index contention"라는
block contention event를 오랫동안 만나실 수도 있습니다. ㅎㅎ

이 내용은 metalink note 183612.1을 참고했습니다.



오라클에서 완벽하게(!) 최적화된(!) 새로운 storage 제품이 나왔답니다.
한번 읽어보세요..

Exadata Architecture

ORACLE EXADATA STORAGE SERVER


2009.11.06 update
벌써 exadata v2가 발표되었네요.
v1과는 달리 SUN 장비에 OLTP용 머신으로 2009 OOw에서 발표되었습니다.
자세한 내용은 아래에..





RMAN 을 벌려놓긴 했는데, 테스트 할 여유가 요즘 별로 없네요.. 일단.. 미루고.. ^^;


오늘 oracle 11g new feature 인 OLTP table compression을 테스트 할 기회가 있어 간단히 정리해 보겠습니다. oracle 9i R2 에서 oracle 은 table compression 기능을 추가했죠. 이미 다른 database에서는 일반화 되어 있었었다죠?  oracle 9i에서는 bulk loading, insert에 대해서만 compression을 지원했습니다. 즉, parallel insert나 sql loader를 이용한 direct loading, 또 Create Table As Select (CTAS)에 대해서만 지원했습니다.

Table compression은 많은 row를 저장하고 있는 대량의 데이터를 위한 기능인데, 대부분의 이러한 테이블은 bulk loading 보다는 batch 작업을 통해 생성되거나 history성 table들이라 이러한 table들은 "move compress"로 다시 compress하는 과정이 추가로 필요하게 되죠..

Oracle 11g에서는 일반적인 DML에 대해서도 compress를 할수 있게 되었습니다. 단지 compress option을 줄때 "for all operations" option을 추가 해 주면 되죠. 물론 이전의 기능으로 사용하려면 "for direct_load operations" option을 주면 됩니다.

create table compress_for_dire compress for direct_load operations as ...
create table compress_for_dire compress for all operations as ...

ps1)
오늘 테스트를 했더니 두 option 다 block의 row가 꽉 차기 전까지는 일반 block과 구조가 동일한 것 같더군요. block 내 row가 꽉차는 시점에 symbol table이 생성되며 compress가 이루어 지는 듯 합니다..

ps2)
"direct_load operations" option을 준 table에 insert  select ( /*+ append */ 빼구) 주니까 당연히 compress는 안됩니다.... 만 일반 table 보다 row가 더 많이 들어가더군요..

왜그럴까?
아시는 분?





tablespace를 만들떄 local managed tablespace를 많이 사용하시죠?
예전의 dictionary-managed 방식에 비해 LMT는 많은 이점이 있죠..
뭐 이점이 있다기 보다는 dictionary-managed 방식의 단점이라고 보는게 더 타당할 지 모르겠네요..^^;

LMT의 extent 관리 방식에는 uniform size와 system managed 방식이 있습니다.
간단히 말하자면, uniform size는 extent size를 정해서 해당 tablespace에 생성되는 segment 들은 동일한 extent size로 설정되게 되고, system managed 방식은 extent size에 대한 설정을 oracle에서 관리해 주는 거죠..

system managed 방식을 쓰면 extent size에 대해 크게 신경을 안써도 되니 좋긴 한데, 오라클에서 어떻게 extent를 관리할까요?

심심해서 함 해봤는데, 엄청난 매카니즘이 숨겨 있더군요.. ㅋ


처음에 64k로 extent가 생성됩니다. 다음 extent도 64K가 생성되죠.. 뭐 이렇게 16개가 만들어지고,
다음은 1024K로 extent가 생성된후... 64개까지 만들어 지고...
..

이런 식으로 extent가 할당되면 1024K가 생성될 때 즈음이면
1024K 이하의 extent는 영원히 짜투리로 남을 수도 있겠죠?


LOCALLY MANAGED TABLESPACE IN ORACLE8I ...





+ Recent posts