레이블이 database인 게시물을 표시합니다. 모든 게시물 표시
레이블이 database인 게시물을 표시합니다. 모든 게시물 표시

2009년 12월 23일 수요일

ORACLE_TIP : How to add and drop online redo log members and groups?

원본 링크 : 클릭! 요새 계속 퍼오기만 하는군요!

 

 

How to add and drop online redo log members and groups?




By Vigyan Kaushik
Dec 08, 2002

Digg! digg!     Print    email to friend Email to Friend

Note: This article was written for educational purpose only. Please refer to the related vendor documentation for detail.




How to add and drop online redo log members and groups?

Redo log Files: The Oracle server maintains online redo log files to minimize the loss of data in the database. The redo log files record all changes made to data in the database buffer cache with some exceptions; for example, in the case of direct writes.

Redo log files are used in a situation such as an instance failure to recover committed data that has not been written to the data files. The redo log files are only used for recovery.

What are online Redo Log Groups?

� A set of identical copies of online redo log files is called an online redo log group.

� The background process LGWR concurrently writes the same information to all online redo log files in a group.

� The Oracle server needs a minimum of two online redo log file groups for the normal operation of a database. Oracle suggests keeping three groups.

What are online Redo Log Members?

� Each online redo log file in a group is called a member.

� Each member in a group has identical log sequence number and the same size. The log sequence number is assigned each time the server starts writing to a log group to identify each redo log file uniquely. The current log sequence number is stored in the control file and in the header of all data files.

How to obtain Information about Groups and Members? The following query returns information about the online redo log file from the control file:

SQL> select group#, sequence#, bytes, members, status from v$log;

GROUP# SEQUENCE# BYTES MEMBERS STATUS

1

215

104857600

1

INACTIVE

2

216

104857600

1

 CURRENT

3

214

104857600

1

INACTIVE

 3 rows selected.

The following query returns information about all members of a group:

SVRMGR> select * from v$logfile;

 

GROUP# STATUS TYPE MEMBER ---------- ------- ------- ---------------------------------------- 3 ONLINE /u02/ORADATA/VTEST/REDO03.LOG 2 ONLINE /u03/ORADATA/VTEST/REDO02.LOG 1 ONLINE /u03/ORADATA/VTEST/REDO01.LOG 3 rows selected.

Adding Online Redo Log Groups : In some cases you might need to create additional log file groups. For example, adding groups can solve availability problems. To create a new group of online redo log files use the following command:

ALTER DATABASE ADD LOGFILE ('/DISK1/log3a.rdo','/DISK2/log3b.rdo') size 1M;

Adding Online Redo Log Members:You can add new member to an existing redo log file group using the following command:

ALTER DATABASE ADD LOGFILE MEMBER
 /DISK2/log1b.rdo' TO GROUP 1,
'/DISK2/log2b.rdo' TO GROUP 2;

Dropping Online Redo Log Groups :To drop a group of online redo log files use the following command:

ALTER DATABASE DROP LOGFILE GROUP 3;

Dropping Online Redo Log Members: To drop a member of an online redo log group use the following command:

ALTER DATABASE DROP LOGFILE MEMBER
'/DISK2/log2b.dbf';

Please note when dropping redo log groups and redo log files, there must be at least two redo log groups and each redo log group must have at least one log member.

 

 
About author:

Vigyan Kaushik is an Oracle certified professional serving IT industry for more than 11 years as an Oracle DBA and System Administrator. He has expertise in Database Designing, Administration, Networking, Tuning, Implementation, Maintenance with web deployment activities on different Unix flavors as well as on Windows Operating Systems.

 

2009년 12월 16일 수요일

ORACLE_TIP : The Secrets of Oracle Row Chaining and Migration(영문)

원본링크

Overview

If you notice poor performance in your Oracle database Row Chaining and Migration may be one of several reasons, but we can prevent some of them by properly designing and/or diagnosing the database.

Row Migration & Row Chaining are two potential problems that can be prevented. By suitably diagnosing, we can improve database performance. The main considerations are:

  • What is Row Migration & Row Chaining ?
  • How to identify Row Migration & Row Chaining ?
  • How to avoid Row Migration & Row Chaining ?

Migrated rows affect OLTP systems which use indexed reads to read singleton rows. In the worst case, you can add an extra I/O to all reads which would be really bad. Truly chained rows affect index reads and full table scans.

Oracle Block

The Operating System Block size is the minimum unit of operation (read /write) by the OS and is a property of the OS file system. While creating an Oracle database we have to choose the «Data Base Block Size» as a multiple of the Operating System Block size. The minimum unit of operation (read /write) by the Oracle database would be this «Oracle block», and not the OS block. Once set, the «Data Base Block Size» cannot be changed during the life of the database (except in case of Oracle 9i). To decide on a suitable block size for the database, we take into consideration factors like the size of the database and the concurrent number of transactions expected.

The database block has the following structure (within the whole database structure)

 Header

Header contains the general information about the data i.e. block address, and type of segments (table, index etc). It Also contains the information about table and the actual row (address) which that holds the data.

Free Space

Space allocated for future update/insert operations. Generally affected by the values of PCTFREE and PCTUSED parameters.

Data

 Actual row data.

FREELIST, PCTFREE and PCTUSED

While creating / altering any table/index, Oracle used two storage parameters for space control.

  • PCTFREE - The percentage of space reserved for future update of existing data.
     
  • PCTUSED - The percentage of minimum space used for insertion of new row data.
    This value determines when the block gets back into the FREELISTS structure.
     
  • FREELIST - Structure where Oracle maintains a list of all free available blocks.

Oracle will first search for a free block in the FREELIST and then the data is inserted into that block. The availability of the block in the FREELIST is decided by the PCTFREE value. Initially an empty block will be listed in the FREELIST structure, and it will continue to remain there until the free space reaches the PCTFREE value.

When the free space reach the PCTFREE value the block is removed from the FREELIST, and it is re-listed in the FREELIST table when the volume of data in the block comes below the PCTUSED value.

Oracle use FREELIST to increase the performance. So for every insert operation, oracle needs to search for the free blocks only from the FREELIST structure instead of searching all blocks.

Row Migration

We will migrate a row when an update to that row would cause it to not fit on the block anymore (with all of the other data that exists there currently).  A migration means that the entire row will move and we just leave behind the «forwarding address». So, the original block just has the rowid of the new block and the entire row is moved.

Full Table Scans are not affected by migrated rows

The forwarding addresses are ignored. We know that as we continue the full scan, we'll eventually get to that row so we can ignore the forwarding address and just process the row when we get there.  Hence, in a full scan migrated rows don't cause us to really do any extra work -- they are meaningless.

Index Read will cause additional IO's on migrated rows

When we Index Read into a table, then a migrated row will cause additional IO's. That is because the index will tell us «goto file X, block Y, slot Z to find this row». But when we get there we find a message that says «well, really goto file A, block B, slot C to find this row». We have to do another IO (logical or physical) to find the row.

Row Chaining

A row is too large to fit into a single database block. For example, if you use a 4KB blocksize for your database, and you need to insert a row of 8KB into it, Oracle will use 3 blocks and store the row in pieces. Some conditions that will cause row chaining are: Tables whose rowsize exceeds the blocksize. Tables with LONG and LONG RAW columns are prone to having chained rows. Tables with more then 255 columns will have chained rows as Oracle break wide tables up into pieces. So, instead of just having a forwarding address on one block and the data on another we have data on two or more blocks.

Chained rows affect us differently. Here, it depends on the data we need. If we had a row with two columns that was spread over two blocks, the query:

SELECT column1 FROM table

where column1 is in Block 1, would not cause any «table fetch continued row». It would not actually have to get column2, it would not follow the chained row all of the way out. On the other hand, if we ask for:

SELECT column2 FROM table

and column2 is in Block 2 due to row chaining, then you would in fact see a «table fetch continued row»

Example

The following example was published by Tom Kyte, it will show row migration and chaining. We are using an 4k block size:

SELECT name,value
  FROM v$parameter
 WHERE name = 'db_block_size';

NAME                 VALUE
--------------      ------
db_block_size         4096

Create the following table with CHAR fixed columns:

CREATE TABLE row_mig_chain_demo (
  x int
PRIMARY KEY,
  a CHAR(1000),
  b CHAR(1000),
  c CHAR(1000),
  d CHAR(1000),
  e CHAR(1000)
);

That is our table. The CHAR(1000)'s will let us easily cause rows to migrate or chain. We used 5 columns a,b,c,d,e so that the total rowsize can grow to about 5K, bigger than one block, ensuring we can truly chain a row.

INSERT INTO row_mig_chain_demo (x) VALUES (1);
INSERT INTO row_mig_chain_demo (x) VALUES (2);
INSERT INTO row_mig_chain_demo (x) VALUES (3);
COMMIT;

We are not interested about seeing a,b,c,d,e - just fetching them. They are really wide so we'll surpress their display.

column a noprint
column b noprint
column c noprint
column d noprint
column e noprint

SELECT * FROM row_mig_chain_demo;

         X
----------
         1
         2
         3

Check for chained rows:

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 0

Now that is to be expected, the rows came out in the order we put them in (Oracle full scanned this query, it processed the data as it found it). Also expected is the table fetch continued row is zero. This data is so small right now, we know that all three rows fit on a single block. No chaining.

Demonstration of the Row Migration

Now, lets do some updates in a specific way. We want to demonstrate the row migration issue and how it affects the full scan:

UPDATE row_mig_chain_demo SET a = 'z1', b = 'z2', c = 'z3' WHERE x = 3;
COMMIT;
UPDATE row_mig_chain_demo SET a = 'y1', b = 'y2', c = 'y3' WHERE x = 2;
COMMIT;
UPDATE row_mig_chain_demo SET a = 'w1', b = 'w2', c = 'w3' WHERE x = 1;
COMMIT;

Note the order of updates, we did last row first, first row last.

SELECT * FROM row_mig_chain_demo;

         X
----------
         3
         2
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 0

Interesting, the rows came out «backwards» now. That is because we updated row 3 first. It did not have to migrate, but it filled up block 1. We then updated row 2. It migrated to block 2 with row 3 hogging all of the space, it had to. We then updated row 1, it migrated to block 3. We migrated rows 2 and 1, leaving 3 where it started.

So, when Oracle full scanned the table, it found row 3 on block 1 first, row 2 on block 2 second and row 1 on block 3 third. It ignored the head rowid piece on block 1 for rows 1 and 2 and just found the rows as it scanned the table. That is why the table fetch continued row is still zero. No chaining.

So, lets see a migrated row affecting the «table fetch continued row»:

SELECT * FROM row_mig_chain_demo WHERE x = 3;

         X
----------
         3

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 0

This was an index range scan / table access by rowid using the primary key.  We didn't increment the «table fetch continued row» yet since row 3 isn't migrated.

SELECT * FROM row_mig_chain_demo WHERE x = 1;

 
        X
----------
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 1

Row 1 is migrated, using the primary key index, we forced a «table fetch continued row».

Demonstration of the Row Chaining

UPDATE row_mig_chain_demo SET d = 'z4', e = 'z5' WHERE x = 3;
COMMIT;

Row 3 no longer fits on block 1. With d and e set, the rowsize is about 5k, it is truly chained.

SELECT x,a FROM row_mig_chain_demo WHERE x = 3;

         X
----------
         3

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 1

We fetched column «x» and «a» from row 3 which are located on the «head» of the row, it will not cause a «table fetch continued row». No extra I/O to get it.

SELECT x,d,e FROM row_mig_chain_demo WHERE x = 3;

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 2

Now we fetch from the «tail» of the row via the primary key index. This increments the «table fetch continued row» by one to put the row back together from its head to its tail to get that data.

Now let's see a full table scan - it is affected as well:

SELECT * FROM row_mig_chain_demo;

         X
----------
         3
         2
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 3

The «table fetch continued row» was incremented here because of Row 3, we had to assemble it to get the trailing columns.  Rows 1 and 2, even though they are migrated don't increment the «table fetch continued row» since we full scanned.

SELECT x,a FROM row_mig_chain_demo;

         X
----------
         3
         2
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 3

No «table fetch continued row» since we didn't have to assemble Row 3, we just needed the first two columns.

SELECT x,e FROM row_mig_chain_demo;

         X
----------
         3
         2
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 4

But by fetching for d and e, we incemented the «table fetch continued row». We most likely have only migrated rows but even if they are truly chained, the columns you are selecting are at the front of the table.

So, how can you decide if you have migrated or truly chained?

Count the last column in that table. That'll force to construct the entire row.

SELECT count(e) FROM row_mig_chain_demo;

  COUNT(E)
----------
         1

SELECT a.name, b.value
  FROM v$statname a, v$mystat b
 WHERE a.statistic# = b.statistic#
   AND lower(a.name) = 'table fetch continued row';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table fetch continued row                                                 5

Analyse the table to verify the chain count of the table:

ANALYZE TABLE row_mig_chain_demo COMPUTE STATISTICS;

SELECT chain_cnt
  FROM user_tables
 WHERE table_name = 'ROW_MIG_CHAIN_DEMO';

 CHAIN_CNT
----------
         3

Three rows that are chained. Apparently, 2 of them are migrated (Rows 1 and 2) and one is truly chained (Row 3).

Total Number of «table fetch continued row» since instance startup?

The V$SYSSTAT view tells you how many times, since the system (database) was started you did a «table fetch continued row» over all tables.

sqlplus system/<password>

SELECT 'Chained or Migrated Rows = '||value
  FROM v$sysstat
 WHERE name = 'table fetch continued row';

Chained or Migrated Rows = 31637

You could have 1 table with 1 chained row that was fetched 31'637 times. You could have 31'637 tables, each with a chained row, each of which was fetched once. You could have any combination of the above -- any combo.

Also, 31'637 - maybe that's good, maybe that's bad. it is a function of

  • how long has the database has been up
  • how many rows is this as a percentage of total fetched rows.
    For example if 0.001% of your fetched are table fetch continued row, who cares!

Therefore, always compare the total fetched rows against the continued rows.

SELECT name,value FROM v$sysstat WHERE name like '%table%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
table scans (short tables)                                           124338
table scans (long tables)                                              1485
table scans (rowid ranges)                                                0
table scans (cache partitions)                                           10
table scans (direct read)                                                 0
table scan rows gotten                                             20164484
table scan blocks gotten                                            1658293
table fetch by rowid                                                1883112
table fetch continued row                                             31637table lookup prefetch client count                                        0

How many Rows in a Table are chained?

The USER_TABLES tells you immediately after an ANALYZE (will be null otherwise) how many rows in the table are chained.

ANALYZE TABLE row_mig_chain_demo COMPUTE STATISTICS;
SELECT chain_cnt,
       round(chain_cnt/num_rows*100,2) pct_chained,
       avg_row_len, pct_free , pct_used
  FROM user_tables
WHERE table_name = 'ROW_MIG_CHAIN_DEMO';
 CHAIN_CNT PCT_CHAINED AVG_ROW_LEN   PCT_FREE   PCT_USED
---------- ----------- ----------- ---------- ----------
         3         100        3691         10         40

PCT_CHAINED shows 100% which means all rows are chained or migrated.

List Chained Rows

You can look at the chained and migrated rows of a table using the ANALYZE statement with the LIST CHAINED ROWS clause. The results of this statement are stored in a specified table created explicitly to accept the information returned by the LIST CHAINED ROWS clause. These results are useful in determining whether you have enough room for updates to rows.

Creating a CHAINED_ROWS Table

To create the table to accept data returned by an ANALYZE ... LIST CHAINED ROWS statement, execute the UTLCHAIN.SQL or UTLCHN1.SQL script in $ORACLE_HOME/rdbms/admin. These scripts are provided by the database. They create a table named CHAINED_ROWS in the schema of the user submitting the script.

create table CHAINED_ROWS (
  owner_name         varchar2(30),
  table_name         varchar2(30),
  cluster_name       varchar2(30),
  partition_name     varchar2(30),
  subpartition_name  varchar2(30),
  head_rowid         rowid,
  analyze_timestamp  date
);

After a CHAINED_ROWS table is created, you specify it in the INTO clause of the ANALYZE statement.

ANALYZE TABLE row_mig_chain_demo LIST CHAINED ROWS;

SELECT owner_name,
       table_name,
       head_rowid
 FROM chained_rows
OWNER_NAME                     TABLE_NAME                     HEAD_ROWID
------------------------------ ------------------------------ ------------------
SCOTT                          ROW_MIG_CHAIN_DEMO             AAAPVIAAFAAAAkiAAA
SCOTT                          ROW_MIG_CHAIN_DEMO             AAAPVIAAFAAAAkiAAB

How to avoid Chained and Migrated Rows?

Increasing PCTFREE can help to avoid migrated rows. If you leave more free space available in the block, then the row has room to grow. You can also reorganize or re-create tables and indexes that have high deletion rates. If tables frequently have rows deleted, then data blocks can have partially free space in them. If rows are inserted and later expanded, then the inserted rows might land in blocks with deleted rows but still not have enough room to expand. Reorganizing the table ensures that the main free space is totally empty blocks.

The ALTER TABLE ... MOVE statement enables you to relocate data of a nonpartitioned table or of a partition of a partitioned table into a new segment, and optionally into a different tablespace for which you have quota. This statement also lets you modify any of the storage attributes of the table or partition, including those which cannot be modified using ALTER TABLE. You can also use the ALTER TABLE ... MOVE statement with the COMPRESS keyword to store the new segment using table compression.

  1. ALTER TABLE MOVE

    First count the number of Rows per Block before the ALTER TABLE MOVE

    SELECT dbms_rowid.rowid_block_number(rowid) "Block-Nr", count(*) "Rows"
      FROM row_mig_chain_demo
    GROUP BY dbms_rowid.rowid_block_number(rowid) order by 1;
     Block-Nr        Rows
    ---------- ----------
          2066          3

    Now, de-chain the table, the ALTER TABLE MOVE rebuilds the row_mig_chain_demo table in a new segment, specifying new storage parameters:

    ALTER TABLE row_mig_chain_demo MOVE
       PCTFREE 20
       PCTUSED 40
       STORAGE (INITIAL 20K
                NEXT 40K
                MINEXTENTS 2
                MAXEXTENTS 20
                PCTINCREASE 0);
    Table altered.

    Again count the number of Rows per Block after the ALTER TABLE MOVE

    SELECT dbms_rowid.rowid_block_number(rowid) "Block-Nr", count(*) "Rows"
      FROM row_mig_chain_demo
    GROUP BY dbms_rowid.rowid_block_number(rowid) order by 1;

     Block-Nr        Rows
    ---------- ----------
          2322          1
          2324          1
          2325          1

     
  2. Rebuild the Indexes for the Table
    Moving a table changes the rowids of the rows in the table. This causes indexes on the table to be marked UNUSABLE, and DML accessing the table using these indexes will receive an ORA-01502 error. The indexes on the table must be dropped or rebuilt. Likewise, any statistics for the table become invalid and new statistics should be collected after moving the table.

    ANALYZE TABLE row_mig_chain_demo COMPUTE STATISTICS;

    ERROR at line 1:
    ORA-01502: index 'SCOTT.SYS_C003228' or partition of such index is in unusable
    state

    This is the primary key of the table which must be rebuilt.

    ALTER INDEX SYS_C003228 REBUILD;Index altered.

    ANALYZE TABLE row_mig_chain_demo COMPUTE STATISTICS;Table analyzed.

    SELECT chain_cnt,
           round(chain_cnt/num_rows*100,2) pct_chained,
           avg_row_len, pct_free , pct_used
      FROM user_tables
     WHERE table_name = 'ROW_MIG_CHAIN_DEMO';

     CHAIN_CNT PCT_CHAINED AVG_ROW_LEN   PCT_FREE   PCT_USED
    ---------- ----------- ----------- ---------- ----------
             1       33.33        3687         20         40

    If the table includes LOB column(s), this statement can be used to move the table along with LOB data and LOB index segments (associated with this table) which the user explicitly specifies. If not specified, the default is to not move the LOB data and LOB index segments.

Detect all Tables with Chained and Migrated Rows

Using the CHAINED_ROWS table, you can find out the tables with chained or migrated rows.

  1. Create the CHAINED_ROWS table

    cd $ORACLE_HOME/rdbms/admin
    sqlplus scott/tiger
    @utlchain.sql
     
  2. Analyse all or only your Tables

    SELECT 'ANALYZE TABLE '||table_name||' LIST CHAINED ROWS INTO CHAINED_ROWS;'
      FROM user_tables
    /


    ANALYZE TABLE ROW_MIG_CHAIN_DEMO LIST CHAINED ROWS INTO CHAINED_ROWS;
    ANALYZE TABLE DEPT LIST CHAINED ROWS INTO CHAINED_ROWS;
    ANALYZE TABLE EMP LIST CHAINED ROWS INTO CHAINED_ROWS;
    ANALYZE TABLE BONUS LIST CHAINED ROWS INTO CHAINED_ROWS;
    ANALYZE TABLE SALGRADE LIST CHAINED ROWS INTO CHAINED_ROWS;
    ANALYZE TABLE DUMMY LIST CHAINED ROWS INTO CHAINED_ROWS;
    Table analyzed.
     
  3. Show the RowIDs for all chained rows

    This will allow you to quickly see how much of a problem chaining is in each table. If chaining is prevalent in a table, then that table should be rebuild with a higher value for PCTFREE

    SELECT owner_name,
           table_name,
           count(head_rowid) row_count
      FROM chained_rows
    GROUP BY owner_name,table_name
    /


    OWNER_NAME                     TABLE_NAME                      ROW_COUNT
    ------------------------------ ------------------------------ ----------
    SCOTT                          ROW_MIG_CHAIN_DEMO                      1

Conclusion

Migrated rows affect OLTP systems which use indexed reads to read singleton rows. In the worst case, you can add an extra I/O to all reads which would be really bad. Truly chained rows affect index reads and full table scans.

  • Row migration is typically caused by UPDATE operation

  • Row chaining is typically caused by INSERT operation.

  • SQL statements which are creating/querying these chained/migrated rows will degrade the performance due to more I/O work.

  • To diagnose chained/migrated rows use ANALYZE command , query V$SYSSTAT view

  • To remove chained/migrated rows use higher PCTFREE using ALTER TABLE MOVE.

2009년 12월 9일 수요일

ORACLE_TIP : DYNAMIC SGA

OTN Discussion Forums 에서 SGA에 관한 문서를 긁어옵니다. 원본은 여기를 클릭하세요~

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

 

PURPOSE



Oracle 9i의 새 기능인 동적으로 SGA 파라미터들을 변경하는 방법에
대하여 알아보기로 한다.

Explanation



Oracle 8i까지는 Buffer Cache, Shared Pool, Large Pool 등과 같은 SGA
파라미터들에 대해 그 크기를 동적으로, db가 운영 중인 상태에서는 변경할
수가 없었다.
즉, 이러한 파라미터들을 변경하려면 db를 shutdown하고 initSID.ora 화일에
서 그 크기를 다시 설정하고, 이 파라미터를 이용해서 db 인스턴스를 restart
해야만 했었다.

Oracle 9i에서는 DBA가 ALTER SYSTEM 명령을 이용해서 SGA 파라미터의 크기
를 동적으로 변경할 수 있게 되었다. 이 특정을 'Dynamic SGA'라고 부른다.

SGA 전체의 최대 크기(SGA_MAX_SIZE)를 정의하고 그 한도 내에서 파라미터의
크기를 변경할 수 있는 것이다. 데이타베이스를 shutdown/startup 없이 작업
이 가능하기 때문에 'Planned Downtime'을 줄이는 한 방법으로도 이해할 수
있다.

이 글에서는 SGA에 할당할 수 있는 최소 단위인 'Granule'의 개념을 살펴보
고, 이 granule이 어떠한 방법에 의해 동적으로 할당되는지에 대해 알아보고
자 한다.
또한 Buffer Cache 파라미터 중 새로운 것과 이전 버전에 비해 달라진 내용
을 소개하기로 한다.

1. Granule

Granule은 가상 메모리 상의 연속된 공간으로, dynamic SGA 모델에서 할당할
수 있는 최소 단위이다. 이 granule의 크기는 SGA 전체의 추정값
(SGA_MAX_SIZE)에 따라 다음과 같이 구분된다.

4MB if estimated SGA size is < 128M
16MB otherwise

SGA의 Buffer Cache, Shared Pool, Large Pool 등의 파라미터는 이 granule
단위로 늘어나거나 줄어들 수 있다. (현재 dynamic SGA를 사용할 수 있는
SGA 관련 파라미터는 Buffer Cache, Shared Pool, Large Pool 세 가지이다.)

2. Dynamic SGA(DB_CACHE_SIZE, SHARED_POOL_SIZE)

DBA는 ALTER SYSTEM 명령을 통해 initSID.ora 화일에 정의된 SGA 관련 파라미
터 값을 동적으로 변경할 수 있다. SGA 파라미터의 크기를 늘려주기 위해서
는 필요한 만큼의 free granule이 존재해야만 하며, 현재 사용하고 있는 SGA
의 크기가 SGA_MAX_SIZE보다 작아야 한다. Free granule이 없다고 해서 다른
파라미터로부터 granule을 free시켜서 그 granule을 이용할 수 있는 것은 아
니다.
반드시 DBA가 명시적으로 free/allocate해야 한다.

다음의 예를 살펴보자. 설명을 단순화하기 위해 이 경우는 SGA가 Buffer
Cache와 Shared Pool로만 구성되었다고만 하자.

예) initSID.ora
SGA_MAX_SIZE = 128M
DB_CACHE_SIZE = 96M
SHARED_POOL_SIZE = 32M

Note : DB_CACHE_SIZE는 Oracle 9i에 새롭게 도입된 파라미터이다.

위와 같은 상태일 때 동적으로 SHARED_POOL_SIZE를 64M로 늘리면 에러가 발생
한다.

SQL> ALTER SYSTEM SET SHARED_POOL_SIZE=64M;
(insufficient memory error message)

이 에러는 SHARED_POOL_SIZE를 늘림으로써 전체 SGA의 크기가 SGA_MAX_SIZE
보다 커지기 때문에 발생한다. (96M + 64M > 128M)

이를 해결하기 위해서는 DB_CACHE_SIZE를 줄인 후, SHARED_POOL_SIZE를 늘린다.

SQL> ALTER SYSTEM SET DB_CACHE_SIZE=64M;
SQL> ALTER SYSTEM SET SHARED_POOL_SIZE=64M;

Note : DB_CACHE_SIZE가 shrink되는 동안에
ALTER SYSTEM SET SHARED_POOL_SIZE=64M;
를 하면 insufficient error가 발생할 수도 있다.
이 경우는 DB_CACHE_SIZE가 shrink된 후 다시 수행하면 정상적으로
수행이 된다.

Note : 위 예제의 경우 estimated SGA 크기가 128M 이상이므로, granule의
단위는 16M이다. 따라서 SGA 파라미터의 크기를 16M의 정수배로 했다.
16M의 정수배가 아닌 경우는 지정한 값보다 큰 값에 대해 16M의
정수배 중 가장 가까운 값을 택하게 된다.

즉, 아래 두 문장의 결과는 똑같다.

SQL> ALTER SYSTEM SET SHARED_POOL_SIZE=64M;

SQL> ALTER SYSTEM SET SHARED_POOL_SIZE=49M;


Note : LARGE_POOL_SIZE 와 JAVA_POOL_SIZE 파라미터는 동적으로 변경하는
것이 불가능하다.

1) Dynamic Shared Pool

인스턴스 start 후, Shared Pool의 크기는 다음과 같은 명령에 의해 동적으
로 변경(grow or shrink)될 수 있다.

ALTER SYSTEM SET SHARED_POOL_SIZE=64M;

다음과 같은 제약 사항이 있다.

- 실제 할당되는 크기는 16M의 정수배가 된다.
- 전체 SGA의 크기는 SGA_MAX_SIZE를 초과할 수는 없다.


2) Dynamic Buffer Cache

인스턴스 start 후, Buffer Cache의 크기는 다음과 같은 명령에 의해 동적으
로 변경(grow or shrink)될 수 있다.

ALTER SYSTEM SET DB_CACHE_SIZE=96M;

다음과 같은 제약 사항이 있다.

- 실제 할당되는 크기는 16M의 정수배가 된다.
- 전체 SGA의 크기는 SGA_MAX_SIZE를 초과할 수는 없다.
- DB_CACHE_SIZE는 0이 될 수 없다.

3. Buffer Cache 파라미터의 변경된 내용

여기서는 Buffer Cache 파라미터와 관련하여 Oracle 9i에 의미가 없어진 파라
미터와 새롭게 추가된 파라미터, 그리고 dynamic SGA 중 Buffer Cache와 관련
이 있는 부분에 대해 기술하고자 한다.

1) Deprecated Buffer Cache Parameters

다음의 세 가지 파라미터는 backward compatibility를 위해 존재하는 것으
로, 차후 의미가 없어진다.

- DB_BLOCK_BUFFERS
- BUFFER_POOL_KEEP
- BUFFER_POOL_RECYCLE

위의 파라미터들이 정의되어 있으면 이 값들을 사용하게 될 것이다. 하지만,
다음에 나올 새로운 파라미터들을 사용하는 것이 좋으며, 만일 위 파라미터
(DB_BLOCK_BUFFERS, BUFFER_POOL_KEEP, BUFFER_POOL_RECYCLE) 값들을 사용
한다면 이 글에서 설명한 dynamic SGA 특징을 사용할 수는 없다. 또한
initSID.ora 화일에 위 파라미터들과 새로운 파라미터를 동시에 기술한다면
에러가 발생한다.

2) New Buffer Cache Sizing Parameters

다음의 세 파라미터가 추가되었다. 이 파라미터들은 primary block size에
대한 buffer cache 정보를 다루고 있다.

- DB_CACHE_SIZE
- DB_KEEP_CACHE_SIZE
- DB_RECYCLE_CACHE_SIZE

DB_CACHE_SIZE 파라미터에 지정된 값은 primary block size에 대한 default
Buffer Pool의 크기를 의미한다. 또한 이전 버전과 마찬가지로 KEEP과
RECYCLE buffer pool을 둘 수 있는데, 이는 DB_KEEP_CACHE_SIZE,
DB_RECYCLE_CACHE_SIZE 라는 파라미터를 이용한다.

이전 버전과 다른 점은 이전 버전의 경우 각각의 파라미터
(DB_BLOCK_BUFFERS, BUFFER_POOL_KEEP,BUFFER_POOL_RECYCLE)에 정의된 값들
이 buffer 갯수(즉, 실제 메모리 크기를 구하려면 db_block_size를 곱했어야
했다. )였는데 반해 이제는 구체적인 메모리 크기이다.

또한 이전에는 DB_BLOCK_BUFFERS가 BUFFER_POOL_KEEP, BUFFER_POOL_RECYCLE
의 값을 포함하고 있었지만, 이제는 DB_CACHE_SIZE가 DB_KEEP_CACHE_SIZE,
DB_RECYCLE_CACHE_SIZE를 포함하고 있지 않다.
즉, 각각의 파라미터들은 독립적이다.

Note : Oracle 9i부터는 multiple block size(2K, 4K, 8K, 16K, 32K)를 지원한다.
위에서 언급한 primary block size는 DB_BLOCK_SIZE에 의해 정해진 block
size를 의미한다. (SYSTEM tablespace는 이 block size를 이용한다.)

3) Dynamic Buffer Cache Size Parameters

바로 위에서 언급한 세 파라미터는 아래와 같이 ALTER SYSTEM 명령에 의해
동적으로 변경 가능하다.

SQL> ALTER SYSTEM SET DB_CACHE_SIZE=96M;
SQL> ALTER SYSTEM SET DB_KEEP_CACHE_SIZE=16M;
SQL> ALTER SYSTEM SET DB_RECYCLE_CACHE_SIZE=16M;

Example


none

Reference Documents


<Note:148495.1>

2009년 9월 28일 월요일

ORACLE_021. Making User Managed Backups_Part II

Making User Managed Backups_Part II


Making User-Managed Backups of the Controlfile
 Archivelog Mode에서 데이터베이스의 구조적 변경이 있었다면 콘트롤 파일을 백업합니다. 콘트롤 파일을 백업하기 위해서는 ALTER DATABASE 시스템 권한이 필요합니다.

 콘트롤 파일을 백업하기 위해서 두가지 방법중 하나를 사용할 수 있습니다.
  - 이진 파일(Binary file)로 콘트롤 파일 백업하기
  - 추적 파일(Trace file)로 콘트롤 파일 백업하기

 


Backing Up the Control File to a Binary File
 콘트롤 파일을 백업하는 가장 일반적인 방법은 SQL 구문을 이용하여 이진 파일로 만들어 백업하는 방법입니다. 이진파일은 추적파일보다 일반적으로 더 선호하게 되는데 이는 아카이브로그 이력, 읽기 전용과 오프라인 테이블 스페이스에 대한 오프라인 기간, 백업셋과 카피(RMAN을 사용시)에 대한 추가적인 정보를 포함하고 있기 때문입니다.

 데이터베이스 구조적 변화 이후 콘트롤 파일 백업하기
 1. 데이터베이스를 변경한다고 가정합니다. 예를 들어 테이블 스페이스를 추가한다고 가정하면
  SQL>ALTER TABLESPACE tbs_1 DATAFILE 'file1.dbf' SIZE 10M;

 2. 이진 파일로 추출될 파일 이름을 정하고 콘트롤 파일을 백업합니다. 다음 SQL문을 참고하십시요.
   SQL>ALTER DATABASE BACKUP CONTROLFILE TO '/backup/contfile.bak' REUSE;

  REUSE 옵션을 사용하면 기존에 백업한 콘트롤 파일이 존재하면 덮어 씌우게 합니다.

 

 

Backing Up the Control File to a trace File
 ALTER DATABASE BACKUP CONTROLFILE 구문의 TRACE 옵션은 콘트롤파일을 관리하고 복구하는데 도움을 줄 것 입니다. TRACE 옵션은 바이너리 파일로 생성하는 대신 SQL 구문을 데이터베이스의 추적 파일에 기록하게 함을 나타냅니다. 추적 파일(trace file) 의 구문은 데이터베이스를 시작하고, 콘트롤 파일을 재 생성하며, 복구하고 데이터베이스를 오픈하는 것으로 이루어져 있습니다.

 추적 파일로 콘트롤 파일을 백업하기 위해 마운트나 오픈상태의 데이터베이스에서 다음 SQL구문을 수행합니다.

  SQL>ALTER DATABASE BACKUP CONTROL FILE TO TRACE;

 RESETLOGS나 NORESETLOGS 를 SQL 구문에 지정하지 않았다면, 생성된 추적파일에는 CREATE CONTROLFILE ... NORESETLOGS 구문이 포함되게 됩니다. 이진 파일로의 백업과 마찬가지로 임시파일 (temp file)의 엔트리는 기록되지 않습니다.

 

 Backing Up the Control File to a Trace File : Example
 sales 데이터베이스의 콘트롤 파일을 재생성 하는 스크립트를 하나 만든다고 가정합니다. 데이터베이스는 다음과 같은 특징을 가지고 있습니다.

 - 세개의 스레드, 스레드 2는 공용(Public) 스레드 3은 개인용(Private)
 - 리두 로그는 2개의 멤버를 가진 3개의 그룹으로 멀티플렉싱
 - 데이터베이스는 다음 데이터 파일을 소유.
   /diska/prod/sales/db/filea.dbf (온라인 테이블스페이스에서 오프라인 데이터파일)
   /diska/prod/sales/db/database1.dbf (온라인 상태의 시스템 테이블 스페이스)
   /diska/prod/sales/db/fileb.dbf (읽기 전용 테이블 스페이스)

 CREATE CONTROLFILE ... NORESETLOGS 구문을 포함한 추적 파일을 만들기 위해 다음을 입력합니다.

  SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE NORESETLOGS;

 그리고 추적파일을 만든 시점의 현재 콘트롤 파일에 기반한 SALES 데이터베이스의 새로운 콘트롤 파일을 만드는 스크립트를 만들기 위해 추적 파일을 수정합니다. 보통 상태의 오프라인 혹은 읽기 전용 테이블 스페이스를 복구하는 절차를 피하기 위해, CREATE CONTROLFILE 구문에서 이들을 제외합니다. 재생성된 콘트롤 파일로 데이터베이스를 오픈하면 이 무시된 파일들은 딕셔너리의 체크코드에 'MISSING'으로 기록됩니다. 이제 ALTER DATABASE RENAME FILE 구문을 이용하여 원래의 파일 이름으로 연결해 주면 됩니다.

 예를 들어 CREATE CONTROLFILE ... NORESETLOGS 스크립트를 MISSING 으로 라벨된 파일을 변경하면서 다음과 같이 수정할 수 있습니다.

# 다음 구문은 새로운 콘트롤 파일을 만들고 이를 이용해서 데이터 베이스를 오픈합니다.
# 로그이력과 RMAN의 메타데이터는 손실될 것 입니다. 추가적인 로그가 오프라인 데이터파일의 복구를 위해
# 요구될 수 있습니다. 온라인 로그가 사용가능할때만 이 방법을 사용하도록 하십시요.

STARTUP NOMOUNT
CREATE CONTROLFILE REUSE DATABASE SALES NORESETLOGS ARCHIVELOG
     MAXLOGFILES 32
     MAXLOGMEMBERS 2
     MAXDATAFILES 32
     MAXINSTANCES 16
     MAXLOGHISTORY 1600
LOGFILE
     GROUP 1
       '/diska/prod/sales/db/log1t1.dbf',
       '/diskb/prod/sales/db/log1t2.dbf'
     )  SIZE 100K
    GROUP 2
       '/diska/prod/sales/db/log2t1.dbf',
        '/diskb/prod/sales/db/log2t2.dbf'
    ) SIZE 100K,
    GROUP 3
       '/diska/prod/sales/db/log3t1.dbf',
       '/diskb/prod/sales/db/log3t2.dbf'
    ) SIZE 100K
DATAFILE
    '/diska/prod/sales/db/database1.dbf',
    '/diskb/prod/sales/db/filea.dbf'
;

# 이 데이터파일은 오프라인이지만 테이블스페이스는 온라인입니다. 데이터파일을 수동으로 오프라인 합니다.

ALTER DATABASE DATAFILE '/diska/prod/sales/db/filea.dbf' OFFLINE;

# 데이터파일이 백업본으로부터 복원되었거나 최근 SHUTDOWN 이 NORMAL 이나 IMMEDIATE가 아니면
# 복구작업이 필요합니다.

RECOVER DATABASE;

# 모든 리두 로그를 아카이빙 하고 로그를 스위치 합니다.

ALTER SYSTEM ARCHIVE LOG ALL;

# 이제 데이터베이스를 정상적으로 오픈할 수 있습니다.

ALTER DATABASE OPEN;

# 백업 콘트롤 파일은 읽기 전용과 노말 오프라인 테이블스페이스의 목록을 가지고 있지 않기때문에
# 그들의 복구수행을 하지않게 할 수 잇습니다. 데이터 딕셔너리(Data Dictionary)를 체크하고 존재하지 않는 파
# 일들의 정보를 찾아 'MISSINGxxxx'로 마킹합니다. 그러면 이름을 다시 설정하여 미싱 파일들을 복구작업 없이
# 살려낼 수 있습니다.
ALTER DATABASE RENAME FILE 'MISSING0002'
     TO '/diska/prod/sales/db/fileb.dbf';

 

 

 

Making User-Managed backups of Archive Redo Logs

 아카이빙 로그를 쌓아두는 디스크의 공간을 절약하기 위해서 백업된 아카이브 로그를 테입이나 다른 디스크에 백업하기를 원할 것 입니다. 만약 아카이브를 여러 위치에 저장한다면, 각각의 로그 스퀀스 번호의 한 카피만 백업하도록 하십시요.

 아카이브 로그 모드에서의 백업
 1. 데이터베이스가 어떤 아카이브 로그 파일을 생성하는지 확인하기 위해 V$ARCHIVED_LOG 를 조회합니다.

  SQL>SELECT THREAD#, SEQUENCE#, NAME
         FROM V$ARCHIVED_LOG;

 2. 각각의 로그 시퀀스 번호당 하나의 카피만 OS 명령어를 이용하여 백업합니다.
  % cp /oracle/dbs/arc_dest/* /disk7/log_backups

 

 

 

CONTINUE...

2009년 9월 11일 금요일

ORACLE_018. Managing Tablespace _ Part 2

Managing Tablespace : Part 2


COALESCING FREE SPACE IN DMT
 Dictionary- Managed tablespaces(DMT) 는 단편화가 일어나 새로운 익스텐트(Extent)를 할당하는데 어려움이 생길 수 있습니다. 이번 포스팅에서는 이러한 단편화된 공간을 정리하는 방법에 대해서 알아보겠습니다.

 
How Oracle Coalesces Free Space
 DMT에서의 빈 익스텐트는 인접해 있는 비어있는 블록들의 모음도 포함합니다. 테이블스페이스 세그먼트에 새로운 익스텐트를 할당할때, 요구된 사이즈는 가장 근접한 비어있는 익스텐트에 할당하게 됩니다. 세그먼트를 드롭하는 몇몇의 경우 세그먼트가 포함하고 있던 익스텐트는 해제되고 비어있는 공간임을 표시합니다. 하지만 해제되어 비어있는 익스텐트는 큰 비어있는 익스텐트에 바로 융합되지 않습니다. 결과적으로 좀더 큰 익스텐트를 할당하는데 있어 좀더 어려운 상황을 맞이하게 됩니다.

 단편화는 다음 몇몇의 경우에 발생하게 됩니다.

  - 세그먼트에 새로운 익스텐트를 할당할시 오라클은 우선 새로운 익스텐트가 들어갈 수
   있을 정도의 충분히 큰 빈 익스텐트를 찾습니다. 어떤 빈 익스텐트도 요구하는 크기보다
   크지 않을때 테이블 스페이스 내에서 인접해 있는 비어있는 익스텐트들을 합치고 다시
   빈 익스텐트를 검색합니다. 새로운 익스텐트 할당을 할 수 없을 시 오라클은 항상 이 작업
   을 수행합니다.

  - SMON 백그라운드 프로세서는 PCTINCREASE 값이 0이 아닐경우 정기적으로 이웃해 있
   는 비어있는 익스텐트의 병합 작업을 수행합니다. PCTINCREASE=0 으로 설정해 놓으면
   빈 익스텐트의 병합은 일어나지 않습니다. SMON 이 병합에 의해 오버헤드가 발생하는 것
   이 걱정이 되면 PCTINCREASE=0 으로 설정하고, 정기적으로 익스텐트를 수동으로 병합
   하면 됩니다.
  - 세그먼트가 드롭(DROP) 되거나 잘릴때 (TRUNCATE) PCTINCREASE 값이 0이 아닐때
   익스텐트의 병합이 일어나고, 이 값이 0이 아니어도 역시 병합이 수행됩니다.
  - ALTER TABLESPACE ... COALESCE 명령으로 수동으로 병합을 수행할 수 있습니다.


                <Pic : Coalescing Free Space>

 Manually Coalescing Free Space
 비어있는 공간의 단편화가 심하다는 것을 확인했다면, ALTER TABLESPACE ... COALESCE 명령을 통해 익스텐트를 수동으로 병합할 수 있습니다. ALTER TABLESPACE 의 시스템 권한을 요구합니다.

 PCTINCREASE=0일때나 SMON의 부하를 조금이라도 줄이기 위해 이 명령어를 사용할 수 있고 할당된 익스텐트를 병합할때 사용합니다. 만약 테이블스페이스에 할당된 익스텐트의 크기가 모두 같다면 병합 작업은 필요하지 않습니다. 이는 아마도 PCTINCREASE 값이 0으로 설정되어 있을 경우이거나 테이블 스페이스의 스토리지 파라메터인 INITIAL, MINIMUM EXTENT, NEXT 값이 모두 같을 경우 일 것 입니다.

 다음 구문은 tabsp_4 테이블스페이스의 빈 공간을 병합하는 명령입니다.

  ALTER TABLESPACE tabsp_4 COALESCE

 다른 ALTER TABLESPACE .. 명령과 마찬가지로 COALESCE 옵션은 베타적입니다. 즉, 다른 부가적인 옵션은 사용하지 않고 혼자서 쓰입니다.

 이 구문은 데이터 익스텐트에 의해 단편화된 빈 공간을 합치지는 않습니다. 데이터 익스텐트 사이사이에 빈 익스텐트가 많이 발견된다면 테이블 스페이스를 재정렬 해야 합니다.(예를들어 Import/Export 를 이용)


 Monitoring Free Space
 테이블 스페이스의 빈 공간을 조회하기 위해 다음 뷰를 사용합니다.

  - DBA_FREE_SPACE
  - DBA_FREE_SPACE_COALESCED

 다음 구문은 tabsp_4 테이블 스페이스에 대한 공간 정보 입니다.

  SELECT BLOCK_ID, BYTES, BLOCKS
    FROM DBA_FREE_SPACE
    WHERE TABLESPACE_NAME='TABSP_4'
    ORDER BY 1;
 

 BLOCK_ID

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

BYTES

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

BLOCKS

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

 2

16384

2

 4

16384

2

 6

81920

10

 16

16384

2

 27

16384

2

 29

16384

2

 31

16384

2

 33

16384

2

 35

16384

2

 37

16384

2

 39

8192

1

 40

8192

1

 41

19660

24

 13 Rows selected

 이 뷰는 tabsp_4 테이블스페이스에 인접한 병합되어 있지 않는 빈 공간을 보여주고 있습니다. ALTER TABLESPACE COALESCE 구문을 이용하여 이들을 병합하면 다음과 같은 결과를 얻습니다.

 BLOCK_ID

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

BYTES

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

BLOCKS

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

 2

131072

16

27

311296

38

2 Rows selected

 DBA_FREE_SPACE_COALESCED 뷰는 병합활동의 통계를 보여줍니다. 이 뷰는 공간을 병합할지의 여부를 결정하는데 매우 쓸모있습니다.


SPECIFY NONSTANDARD BLOCK SIZE TABLESPACE
 테이블스페이스를 작성시 DB_BLOCK_SIZE 초기화 파라메터에 정의되어 있는 표준 블록 사이즈와 다른 크기의 블록 사이즈를 가진 테이블 스페이스를 만들 수 있습니다. 이 기능은 표준 블록 사이즈가 다른 데이터베이스 간에 테이블을 주고 받을 수 있게 합니다.

 CREATE TABLESPACE 구문의 BLOCKSIZE 단서는 표준 블록 사이즈와 다른 블록 사이즈를 갖는 테이블 스페이스를 만들 수 있게 해 줍니다. 단, SGA에 비표준 블록사이즈의 퍼퍼 캐시를 설정해 주어야 합니다.

 다음 구문은 lmtsb 테이블 스페이스를 생성하지만, 표준 블록 사이즈와 다른 블록 사이즈를 가지고 만듭니다.

  CREATE TABLESPACE lmtsb DATAFILE '/u02/oracle/data/lmtsb01.dbf' SIZE 50M
     EXTENT MANAGEMENT LOCAL UNIFORM SIZE 128K
     BLOCKSIZE 8K;

        * BLOCKSIZE nK 단서를 수행하기 위해서는 DB_CACHE_SIZE와 최소 한개의
         DB_nK_CACHE_SIZE 초기화 파라메터를 설정해야 합니다. BLOCKSIZE nK
         에서의 n과 DB_nK_CACHE_SIZE 의 n 값은 반드시 같아야 합니다.



CONTROLLING THE WRITING OF REDO RECORDS
 데이터베이스를 운영중에 리두 레코드(Redo Record) 를 생성 할지 안할지를 정할 수 있습니다. 리두를 생성하지 않는것은 성능을 향상시킬 수 있고, 쉽게 복구가 가능한 행위를 할때 사용할 수 있습니다. 이런 경우는 아마도 CREATE TABLE .. AS SELECT 같은 인스턴스가 실패해도 명령을 반복적으로 수행할 수 있는 경우가 될 것 입니다. 리두를 사용하지 않으면 미디어 복구(Media Recovery)를 수행할 수 없습니다.

 CREATE TABLESPACE 구문의 NOLOGGING 옵션은 테이블스페이스에서 오브젝트가 활동할때 리두를 작성하지 않길 원할때 사용합니다. 이 옵션을 달지 않으면 LOGGING으로 설정되고 테이블스페이스내의 오브젝트가 변경되거나 만들어질때 리두를 기록합니다. 리두는 LOGGING 옵션을 붙인다 하더라도 임시 세그먼트나 임시 테이블스페이스에 관한 기록은 절대 하지 않습니다.

 테이블스페이스 레벨에서 설정한 이 옵션은 테이블스페이스 내에서 생성되는 모든 오브젝트에게 적용됩니다. 이러한 옵션은 스키마 레벨에서 오브젝트를 작성할 때 오버라이드 하여 사용할 수 있습니다. (예를들어 CREATE TABLE 구문)

 스텐바이 데이터베이스의 경우 NOLOGGING 을 설정하는것은 스텐바이 데이터베이스의 정확성과 이용성에 문제를 야기할 수 있습니다. 이 문제를 극복하기 위하여 테이블을 작성시FORCE LOGGING 을 사용할 수 있습니다. 이는 테이블스페이스 내에서 오브젝트의 변화를 강제로 기록할 수 있게 합니다. 이 옵션은 오브젝트 레벨에서 만들어진 모든 객체에 사용 가능합니다.

 FORCE LOGGING 으로 만들어진 테이블 스페이스를 다른 데이터 베이스로 옮기면 새로운 테이블 스페이스는 FORCE LOGGING 옵션은 다루지 않습니다.




FIN.
REF) Oracle Documents.Server.920/a96521 Managing Tablespaces

2009년 9월 8일 화요일

ORACLE_016. Complete Recovery Using Archive Log Mode

Complete Recovery Using Archive Log Mode                                      

OPEN RECOVERY TO SAME DIRECTORY

 STEP 01_장애가 발생한 테이블(혹은 데이터 파일)을 OFFLINE 시킵니다.

 

                  ALTER TABLESPACE tsname OFFLINE IMMEDIATE;       OR

                  ALTER DATABASE DATAFILE 'datafilepath/datafile.dbf' OFFLINE

           

                   * OFFLINE IMMEDIATE 는 CKPT 를 발생하지 않습니다.  따라서 DBWr이

                   호출되지 않기 때문에 장애가 일어난 테이블(혹은 파일)에 기록하는 것을

                   방지할 수 있습니다.

                   * 테이블 스페이스가 들어있는 데이터 파일의 조회는 다음 쿼리를 이용합니다.

                SELECT A.FILE#, A.NAME "Datafile Name", B.NAME "Tablespace Name", status

                      FROM V$DATAFILE A, V$TABLESPACE B

                      WHERE A.TS#=B.TS#

                      ORDER BY B.NAME;

 

 STEP 02_마지막으로 풀 백업한 해당 데이터 파일을 복사합니다.

 

                 UNIX ) cp -f /Backuped_file_path/filename.dbf /target_path/target_name.dbf

                      NT ) copy /Backuped_file_path/filename.dbf /target_path/target_name.dbf

 STEP 03_복원된 파일에 ARCHIVE LOG 파일 및 REDO LOG 파일을 적용시킵니다.

 

                  RECOVER DATAFILE n  // n은 데이터파일 번호

                  * 데이터 파일의 번호는 STEP01의 예제 쿼리를 통해 확인할 수 있습니다.

 

 STEP 04_복구된 테이블 스페이스(혹은 데이터 파일)를 ONLINE 시킵니다.
      
                  ALTER TABLESPACE tsname ONLINE;           OR

                  ALTER DATABASE DATAFILE n ONLINE;

 

OPEN RECOVERY TO DIFFERENT DIRECTORY
 다른 디렉토리에 데이터 파일을 복원하는 방법은 위 방법과 동일합니다. STEP 02에서 원래 데이터 파일의 위치가 있던곳이 아닌 다른곳에 마지막으로 풀 백업된 데이터 파일을 복사합니다. 그리고 콘트롤 파일에 데이터 파일의 위치가 바뀌었음을 알려주면 됩니다.

                  ALTER DATABASE RENAME FILE '원래위치' TO '나중위치'

 콘트롤 파일에 데이터파일의 위치가 바뀌었음을 알려주었으면 그 후는 STEP 03, STEP 04를 다시 수행하시면 됩니다.

CLOSE RECOVERY (SYSTEM TABLE RECOVERY)
 SYSTEM TABLE이 들어있는 데이터 파일을 확인합니다. 위 SELECT 질의를 통해 시스템 테이블 스페이스가 들어있는 데이터 파일을 확인할 수 있습니다. 복구작업을 수행하기 전에, 데이터베이스를 다운시킵니다.

                 SHUTDOWN ABORT

 데이터베이스를 다시 MOUNT 상태로 돌립니다.
 
                 STARTUP MOUNT

 마지막으로 했던 풀 백업에서 해당 파일을 복사해 오고 LOG 파일을 적용합니다.
 
                 RECOVER DATABASE

 마지막으로 데이터베이스를 열어줍니다.

                 ALTER DATABASE OPEN;


FIN.

 

          

2009년 9월 7일 월요일

ORACLE_015.ARCHIVE LOG

ARCHIVE LOG                                                                                  
INTRODUCTION OF ARCHIVE LOG
 모든 트랜젝션(transaction)은 Online Redo Log에 기록이 됩니다. 이 기록들은 예상치 못한 데이터베이스의 오류등에 대비하여 트랜젝션을 롤백하고 최근까지 했던 작업을 자동으로 다시 수행해주는 복구 알고리즘에 있어 굉장히 중요합니다. 이러한 리두로그에 관한 정보는 다음 뷰를 이용하여 조회해 볼 수 있습니다.

 -V$LOG, V$LOGFILE, V$LOG_MEMBER

 예상치 못한 데이터 베이스의 오류에 대하여 항상 준비를 해야 합니다. 그래서 우리는 일정 주기마다 계획적으로 백업을 수행합니다. 백업의 방식 또한 다양합니다. 사용자 백업, 인크리멘탈 백업, 그리고 아카이브 로그 백업입니다(User-managed Back up, Incremental Back up and Archive log back up). 이번 포스트에서는 아카이브 로그의 설정 및 아카이브 로그모드로 DB를 수행하는 방법을 알아보겠습니다.

NOARCHIVE LOG MODE
 처음 데이터베이스 생성시 데이터베이스는 NOARCHIVE LOG 모드로 생성이 됩니다. NOARCHIVE LOG에서는 Redo log 파일이 순환 방식으로 사용이 됩니다. 즉 A로그파일이 다 채워지면 LGWr은 B로그파일에 Transaction을 기록합니다. B가 다 채워지면 다시 A에 기록합니다. 우선 리두 로그가 겹쳐 쓰여지면(재사용 되면) 마지막 전체 백업에서만 복구가 가능합니다.

 

ARCHIVE LOG MODE
 가득 찬 리두 로그 파일은 체크포인트가 일어나고 ARCn 에 의해 백업되기 전까지는 다시 사용할 수 없습니다. 콘트롤 파일의 엔트리에 Archived log file의 Sequence 번호가 기록됩니다.

 인스턴스 복구에서 데이터베이스에 일어난 가장 최근의 변화를 그대로 유지시킬 수 있으며 Archive log는 Media recovery 에서도 사용할 수 있습니다.

 
Automatic Archive
 
자동으로 아카이브를 수행하기 위해서는 다음 파라미터를 설정합니다.

                             LOG_ARCHIVE_START=TRUE

 만약 수동으로 아카이빙을 수행하려면 값을 FALSE 로 바꿔주면 됩니다. 단, 이 상태에서 아카이빙을 하지 않은채로 온라인 리두 로그파일이 가득 차게 될 경우 아카이빙을 할때까지 데이터베이스는 멈춰버립니다.

 Specifying Multiple ARCn Process
 다음의 파라미터를 통해 인스턴스가 시작될때 ARC의 갯수를 정할 수 있습니다.

                             LOG_ARCHIVE_MAX_PROCESSES

 병렬 DDL 혹은 DML 작업은 많은 수의 리두 로그 파일을 생성합니다. 단일 ARC프로세스로 이러한 프로세스를 아카이빙 하는것은 ARC에 많은 부하를 불러 일으킬 것 입니다.

 LOG_ARCHIVE_START 가 TRUE로 되어 있으면 LOG_ARCHIVE_MAX_PROCESSES에 정의된 숫자 만큼(최대 10) ARC를 가지고 인스턴스가 시작됩니다.  이 파라메터는 ALTER SYSTEM SET 구문으로 변경할 수 있습니다.

 Enabling Automatic Archiving After Instance Startup
 인스턴스를 다운하지 않고 ALTER 구문을 이용하여 자동 아카이빙 기능을 사용할 수 있습니다. 다음의 방법을 사용합니다.

                           UNIX) ALTER SYSTEM ARCHIVE LOG START TO '/ORADATA/ARCHIVE1;
                           NT)      ALTER SYSTEM ARCHIVE LOG START TO 'c:\u04\Oracle\Test\log\';
       * <-> ALTER SYSTEM ARCHIVE LOG STOP;

 
SPECIFYING THE ARCHIVE LOG DESTINATION
 아카이브 로그가 저장될 위치를 지정합니다. 다음 두가지 파라메터를 이용합니다.

                           LOG_ARCHIVE_DEST_n     //아카이브 로그가 저장될 위치. 10개까지 지정 가능
                           LOG_ARCHIVE_FORMAT  //아카이브 로그의 파일 형식

 

                          ALTER SYSTEM SET LOG_ARCHIVE_DEST_1="LOCATION=/archive1/";
                          ALTER SYSTEM SET LOG_ARCHIVE_DEST_2="SERVICE=standby_db1";

 Location & Service
 로컬 디스크의 위치에 아카이브 로그 파일을 저장할 시에는 'LOCATION' 구문을 사용합니다. 아카이브 로그 파일이 원격 DB에 있을 경우 Oracle Net Alias 를 'SERVICE' 구문을 사용하여 원격 임을 알려줍니다. 이 Alias 의 정보는 TNSNAMES.ORA 파일의 기록을 참고합니다.  최소한 한개의 LOCATION 옵션을 가진 경로를 설정해 주어야 합니다.

 Mandatory & Optional
 MANDATORY 옵션은 반드시 아카이브 로그가 성공적으로 만들어 져야 할 경우 사용합니다. OPTIONAL 은 성공적으로 만들어지지 않아도 오라클은 신경쓰지 않습니다.

  ALTER SYSTEM SET LOG_ARCHIVE_DEST_1="LOCATION=/archive1/
                                                                                           MANDATORY REOPEN";
  ALTER SYSTEM SET LOG_ARCHIVE_DEST_2="SERVICE=standby_db1
                                                                                           MANDATORY REOPEN REUSE 600";
  ALTER SYSTEM SET LOG_ARCHIVE_DEST_3="LOCATION=/archive2/
                                                                                           OPTINAL";

 
 REOPEN 옵션은 아카이브 로그 파일 생성 실패시 지정된 수의 초만큼 시간이 지난후에 아카이브 로그 파일을 재생성 하기 위한 시도를 합니다. 기본값은 300 입니다. OPTIONAL 로 지정된 것은 에러의 유무와 상관없이 진행됩니다.

 Controlling Archiving to a Destination
 지정된 LOG_ARCHIVE_DEST_n 을 활성화 시키거나 잠시 중지시킬 수 있습니다.  기본값으로는 Enable 되어 있습니다. 만약 잠시 하나의 Dest를 정지 시키고자 한다면 다음 구문을 이용합니다.
 
  ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2 = [ENABLE | DEFER ]


SPECIFYING A MINIMUM NUMBER OF LOCAL DESTINATIONS
 최소 성공해야할 아카이브 로그의 갯수가 몇개인지를 설정합니다. 예를 들어 2로 설정했다면 체크포인트등 로그가 스위치가 되는 이벤트가 발생하고 아카이빙이 시작됬을때, 이때 생성된 아카이브 로그 파일이 최소 두쌍이 되어야 한다는 것을 뜻 합니다. 다음 파라메터를 이용하여 설정할 수 있습니다.

  ALTER SYSTEM SET LOG_ARCHIVE_MIN_SUCCEED_DEST = 2

SPECIFYING THE FILE NAME FORMAT

  LOG_ARCHIVE_FORMAT = extention

 File Name Options
 - %s 혹은 %S : 파일 이름에 log sequence 번호를 넣습니다.
 - %t 혹은 %U : 파일 이름에 thread 번호를 넣습니다.
 - %S : 고정 길이를 사용하게 하며 빈 자리는 0으로 채웁니다.

CHANGING THE ARCHIVE MODE
 CREATE DATABASE 로 첫 데이터베이스를 만들면 기본적으로 NOARCHIVE 상태로 만들어 집니다. ALTER DATABASE 명령을 통해 상태를 변경할 수 있습니다.

 STEP 01) SHUTDOWN IMMEDIATE
 STEP 02) STARTUP MOUNT
 STEP 03) ALTER DATABASE ARCHIVELOG;
 STEP 04) ALTER DATABASE OPEN;
 STEP 05) Take a full backup of the database.

OBTAINING ARCHIVE LOG INFORMATION
 Dynamic Views
 V$ARCHIVED_LOG, V$ARCHIVE_DEST, V$LOG_HISTORY
 V$DATABASE, V$ARCHIVE_PROCESSES

 Command Line
 SQL>ARCHIVE LOG LIST;

 

FIN
REF) Oracle9i DBA Fundamental II
       

2009년 9월 1일 화요일

ORACLE_013. Understanding Access Path : Full Table Scans

Understanding Access Path : Full Table Scans                                          

FULL TABLE SCANS
 이 형식의 스캐닝 방식은 테이블에서 모든 자료를 읽어들인 후 필터를 통해 원하는 행을 얻어내는 방식 입니다. 풀 테이블 스캔이 일어나는 동안 하이워터마크(High Water Mark, HWM)밑에 있는 테이블 블록은 모두 읽혀집니다. 각각의 행은 구문의 where 절의 조건에 맞는지 확인됩니다.

 풀 테이블 스켄이 수행될때 오라클은 모든 블럭을 순차적으로 읽습니다. 이는 블럭들이 근접해 있으면, 하나의 블록을 읽어들이는 것 보다 더 많이 읽어드리기에 프로세스의 속도를 높일 수 있기 때문입니다. 한개의 블럭에서 여러개의 블럭을 읽어드리는 크기는 DB_FILE_MULTIBLOCK_COUNT 파라메터에 나타나 있습니다. 다중 블럭 읽기(multiblcok read)는 풀 테이블 스켄에서 매우 효율적 입니다. 각각의 블록은 단 한번만 읽힙니다.

WHY A FULL TABLE SCAN IS FASTER FOR ACCESSING LARGE AMOUNTS OF DATA
 풀 테이블 스켄은 테이블의 크고 조각난 블록에 접근할 경우 인덱스 범위 스켄(Index Range Scan)보다 비용이 더 싸게 먹힙니다. 풀 테이블 스켄은 큰 I/O 단위를 사용하는데 이는 작은 I/O를 여러번 호출하는 것 보다 비용이 싸기 때문이죠.

WHEN THE OPTIMIZER USES FULL TABLE SCAN
 다음의 경우에 수행합니다.

 Lack of Index
 질의(Query)가 존재하는 인덱스를 사용할 수 없으면, 풀 테이블 스켄을 수행합니다. 인덱싱된 컬럼에 펑션(function)을 사용할 경우 인덱스를 사용하지 않고 풀 테이블 스켄을 사용합니다.
  Example)
  SELECT last_name, first_name
  FROM   employees
  WHERE UPPER(last_name) LIKE :b1

  * 만약 케이스에 의존하는 검색을 수행할 경우 검색하는 컬럼에 대하여 케이스를 섞는것을 허용하지 말거나 펑션 기반의 인덱스, 예를들어 UPPER(last_name)를 만드는 것을 허용하지 마십시요. 좀더 자세한 정보를 원하시면 아래 접어놓은 내용을 참고 하세요. (영문)

 

Function-Based Index

 

 Large Amount of data
  만약 옵티마이저가 생각하기에 테이블의 대부분의 블럭을 읽어들인다 판단하면 인덱스가 존재한다 하더라도 풀 테이블 스켄을 수행합니다.

 Small Tables

  테이블의 하이워터마크 밑의 블럭이  DB_FILE_MULTIBLOCK_COUNT 에 정의되어 있는 값보다 적은 경우, 즉 단 한번의 I/O만으로 테이블을 전부 읽을 수 있는 경우 풀 테이블 스켄을 수행합니다. 이럴경우 인덱스가 존재한다고 하여도 풀 테이블 스켄을 수행합니다.

 

 High Degree of Parallelism

  고도(High Degree)의 테이블 Skew 데이터라면 옵티마이저는 풀 테이블 스켄을 수행합니다. ALL_TABLES에서 DEGREE 값을 확인할 수 있습니다.


FULL TABLE SCAN HINTS
 FULL(table_alias)를 이용하여 테이블 스켄을 강제로 할 수 있습니다.
 
 SELECT /*+ FULL(e) +/ employee_id, last_name
 FROM employees e
 WHERE last_name LIKE :b1;

ASSESSING I/O BLOCKS, NOT ROWS
 오라클은 I/O 단위로 블럭을 다룹니다. 그러므로 옵티마이저는 행의 갯수가 아닌 블럭의 사용률에 따라 풀 테이블을 할지 결정합니다. 이는 인덱스 클러스터링 값으로 불리워집니다. 하나의 블럭에 하나의 행만 존재할시 Row에 접근하는 것과 블록에 접근하는 것이 같은 소요비용이 소모됩니다.

 하지만 대부분의 테이블은 각각의 블록에 여러개의 행을 가지고 있습니다. 그러므로 여러개의 행들을 최소의 블록에 함께 클러스터링 하기를 바랍니다. 그렇지 않으면 많은 수의 블럭에 데이터들이 퍼져나갈 것 입니다.


HIGH WATER MARK(HWM) IN DBA_TABLES
 DDT(Data Dictionary Table)는 삽입된 행이 차지하고 있는 블록의 트랙을 가지고 있습니다. HWM은 풀 테이블 스켄시 끝점을 나타냅니다. HWM은 DBA_TABLES의 BLOCKS에 저장되어 있습니다. 이 값은 테이블이 truncated 혹은 drop 될시 초기화 됩니다.

 예로 과거에 많은 행을 가지고 있던 테이블이 있었다고 가정해 봅시다. 대부분의 행이 최근에 지워졌습니다. 그래서 지금은 HWM 밑의 많은 블럭들이 빈 상태입니다. 이때 풀 테이블 스켄을 수행시 HWM까지 읽어드리기 때문에 좋지 못한 성능을 내게 됩니다.

ROWID SCANS

 각 행의 ROWID는 데이터 파일에 지정되어 있으며 데이터 블록은 행과 그 행위 위치한 정보를 포함하고 있습니다. ROWID 에 의해 위치가 지정된 행은 한개의 행을 가져오는데 가장 빠른 방법입니다.

 ROWID를 이용해 TABLE에 접근하려면 오라클은 우선 WHERE 구문 혹은 하나이상 테이블 인덱스를 통해 선택된 행에 대해서 ROWID를 획득합니다. 그리고 그 행의 ROWID를 이용하여 테이블에 각각 위치시킵니다.

WHEN THE OPTIMIZER USES ROWIDS
 일반적으로 인덱스에서 ROWID를 얻어낸 후의 다음 단계입니다. 인덱스가 존재하지 않는 컬럼에 대해서도 테이블에 대한 접근이 일어날 수 있습니다. ROWID를 이용한 접근방법은 다음에 나올 인덱스 스켄이 필요하지 않습니다. 구문에 사용되는 컬럼이 모두 인덱스가 있다면 ROWID를 이용한 접근은 일어나지 않을 것 입니다.

 

FIN
REF) Oracle Documents (Server .920)/a96533 "Introduction to the Optimizer"

2009년 8월 26일 수요일

ORACLE_010. OPTIMIZER - Choosing Optimizer Approach and Goal

OPTIMIZER - Choosing Optimizer Approach and Goal                        

 기본적으로 CBO의 목표는 최상의 출력결과 입니다. 이는 최소한의 자원을 이용하여 쿼리를 수행하는데 필요한 행을 읽어들이는 방법을 선택하는 것 입니다. 또한 오라클은 반응시간의 최소화를 위한 최적화도 수행합니다. 반응시간이 뜻하는 바는 SQL 구문에 의해 최소의 자원을 이용하여 첫번째 행에 접근하는 방법 입니다.

 

 옵티마이저에 의해 생성된 실행계획은 옵티마이저의 목표에 따라 다양하기도 합니다. 많은 처리량을 위한 최적화는 인덱스 스켄보다 오히려 풀 테이블 스켄이거나 Nested Loop Join 보다 Sort Merge Join 일 수 있습니다. 최상의 반응시간을 위한 최적화는 Index Scan, 혹은 Nested Loop Join 입니다.

 

 예를들어, Sort-Merge 나 Nested Loop 중 하나를 사용하여 Join 구문을 수행한다고 가정해 봅시다. Sort-merge 방식은 아마도 Query 의 모든 결과를 뱉어내는데 빠를 것이고 Nested Loop 방식은 첫번째 행을 뱉어네는데 효율적일 것 입니다. 많은 처리량에 대한 향상이 목표라면 Sort merge join 을 사용하면 될 것 입니다. 반면 좀더 빠른 반응을 원한다면, 옵티마이저는 Nested loop join 을 사용하는게 좋을 것 입니다.

 

  - Oracle Reports Application 과 같은 어플리케이션이 Batch로 동작할때는 처리량에 관해 최적화를 합니다. Batch Application 에서의 처리량은 굉장히 중요한데 사용자는 어플리케이션이 끝마치는 시간이 얼만큼 필요할지만 고려하기 때문입니다. 반응시간은 좀 덜 중요한데, 어플리케이션이 수행되는 동안 개별적으로 실행된 구문의 결과를 계산하지 않기 때문입니다.

 

 - Interactive Applicatoin (대화형 어플리케이션), 예를들어 Oracle Forms App. 나 SQL*Plus 쿼리등은 반응시간에 촛점을 맞춥니다. 사용자들은 구문을 통해 첫번째 행이나 혹은 첫 몇개의 행을 눈으로 확인하기 위해 기다리기 때문입니다.

 

 옵티마이저는 다음과 같은 SQL 문의 요소로 데이터로의 접근과 목표를 최적화 합니다.

  - OPTIMIZER MODE Initialization Parameter

  - CBO Statistics in the Data Dictionary

  - Optimizer SQL Hints for Changing the CBO Goal

OPTIMIZER_MODE INITIALIZATION PARAMETER
 OPTIMIZER_MODE 초기화 파라미터는 인스턴스에서 옵티마이저가 선택할 기본 행동 방법을 설정합니다.

 

Value          Description            

CHOOSE    

 

 

 

 

 

 

 

 

ALL_ROWS

 

 

FIRST_ROWS_n 

 

 

FIRST_ROWS  

 

RULE

 옵티마이저는 Cost-base와 Rule-base중 하나를 선택합니다. 이는 Statistics 가 유효한지에서 결정됩니다.

 

  - DD(Data Dictionary)가 최소 하나의 테이블에 유효한 통계를 가지고 있다면 옵티마이저는 Cost-Based 방식을 사용합니다.

  - DD에 아주 소량의 통계만 있다면 그 값이 유효할때까진 Cost-base 를 사용합니다. 하지만 옵티마이저가 반드시 다른 통계 없이 이 구문을 수행하기 위한 통계를 추측합니다. 이는 차선책의 실행계획을 수행할 수 있습니다.

  - DD에 통계가 전혀 전재하지 않다면 Rule-base 방식을 사용합니다.

 

 통계의 존재 유무를 떠나서 세션의 모든 SQL문에 Cost-base 방식을 사용합니다. 많은 작업량 처리에 적합한 최적화를 실행합니다.(최소의 자원으로 모든 구문을 해결합니다.)

 

 통계의 유무에 상관없이 Cost-base 를 선택합니다. 또한 첫 n 개의 행을 뱉어내기 위해 최소의 시간을 소요하는 최적화를 수행합니다. n값은 1,10,100 혹은 1000 입니다.

 

 옵티마이저는 COST를 섞어 스스로 첫번째 행을 뱉어네는데 가장 좋은 계획을 결정해 냅니다.

 

 RULE-BASE 방식으로 설정합니다. 통계자료의 유무는 고려대상이 아닙니다.

 

 옵티마이저의 파라메터는 다음과 같은 방법으로 변경할 수 있습니다.

 

  ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS_1;

 

OPTIMIZER SQL HINTS FOR CHANGING THE CBO GOAL
 개별적으로 수행하는 SQL 문의 CBO 를 변경하기 위해서 다음의 힌트를 개별 SQL에 삽입할 수 있습니다.

 - FIRST_ROWS(n),   n은 어떤 양수도 가능합니다.

 - FIRST_ROWS

 - ALL-ROWS

 - CHOOSE

 - RULE

 

CBO STATISTICS IN THE DATA DICTIONARY

 CBO가 사용하는 통계정보는 DD(Data Dictionary)에 저장되어 있습니다. DBMS_STATS 패키지나 ANALYZE 구문을 통해 물리적 저장장치의 특성이나 스키마 오브젝트의 데이터 분산정도를 수집할 수 있습니다.

 

       * ORACLE은 ANALYZE 구문보다 DBMS_STATS 패키지를 이용하여 통계정보를 모으는 것을

       권장합니다. 이 패키지는 통계정보를 병렬로 수집 가능하게 해 주며 파티션된 오브젝트의 정보

       를 모을 수 있습니다. 또한 다른 여러가지 방법으로 통계정보를 모을 수 있는 수단을 제공합니

       다. 게다가 CBO 는 DBMS_STATS를 이용해 수집한 통계정보만을 사용할 것 입니다.

 

       하지만 DBMS_STATS 보다 ANALYZE를 반드시 사용해야 할 경우가 있습니다.

        - VALIDATE 혹은 LIST CHAINED ROWS 단서를 달아 사용할때

        - FREELIST BLOCKS 의 정보를 수집할 때

 보다 효과적으로 CBO를 사용하기 위해 존재하는 데이터들의 통계정보를 가지고 있어야 합니다. SKEW DATA라 불리우는 중복되는 넓은 범위의 숫자로 이루어진 컬럼이 있다면 히스토그램 정보를 모으길 권장합니다.

 

 통계정보의 결과는 CBO에게 데이터의 유일함과 분산정도의 정보를 제공합니다. 이 정보를 이용하여 CBO는 높은 수준의 정확한 실행계획의 비용을 계산할 수 있습니다. 이는 CBO가 가장 적은 비용을 소요하여 실행 계획을 선택하는 것을 가능하게 해 줍니다.

FIN
REF) Oracle Documents (Server .920)/a96533 "Introduction to the Optimizer"

 

Next => Understanding the Cost-Based Optimizer