본문 바로가기

Programing/Oracle

Oracle - TABLE 재구성

MIGRATION 


SQL> SHOW USER
USER은 "SCOTT"입니다
SQL> CREATE TABLE ROW_MIG
  2  (NAME VARCHAR2(1))
  3  TABLESPACE USERS;

테이블이 생성되었습니다.

SQL> INSERT INTO ROW_MIG
  2  VALUES ('A');

1 개의 행이 만들어졌습니다.

SQL> INSERT INTO ROW_MIG
  2  SELECT * FROM ROW_MIG;

1 개의 행이 만들어졌습니다.

SQL>/

524288 개의 행이 만들어졌습니다.

SQL> COMMIT;

커밋이 완료되었습니다.


SQL> ALTER TABLE ROW_MIG
  2  MODIFY (NAME VARCHAR2(4000));

테이블이 변경되었습니다.


VARCHAR는 가변적 길이이므로 물리적으로는 변하지 않는다.


SQL> UPDATE ROW_MIG
  2  SET NAME = 'AAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAA';

물리적으로 확보할수 없는 공간에 수만큼 입력했을때 또다른 row로 이동해서 기록된다.

이것이 ROW MIGRATION



데이터 수위

               1                          2

■■■■■■■■■■■ ■■■■■ㅁㅁㅁㅁㅁㅁ

      - BLOCKS -   HIGH WATER MARK EMPTY-    BLOCKS-

 

한번도 사용하지 않은것 : ㅁ

사용된것 : ■

사용한것과 하지 않은것에 중간 : HIGH WATER MARK EMPTY



SQL> DESC DBA_TABLES;
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------

BLOCKS                                           NUMBER
EMPTY_BLOCKS                               NUMBER



  1  SELECT TABLE_NAME,OWNER,BLOCKS,EMPTY_BLOCKS,AVG_ROW_LEN,CHAIN_CNT
  2  FROM DBA_TABLES
  3  WHERE OWNER = 'SCOTT'
  4* AND TABLE_NAME = 'ROW_MIG'
SQL> /

TABLE_NAME                     OWNER                              BLOCKS
------------------------------ ------------------------------ ----------
EMPTY_BLOCKS AVG_ROW_LEN  CHAIN_CNT
------------ ----------- ----------
ROW_MIG                        SCOTT


SQL> --ANALYZE TABLE SCOTT.ROW_MIG ESTIMATE STATISTICS;
SQL> ANALYZE TABLE SCOTT.ROW_MIG COMPUTE STATISTICS;



SQL> ALTER TABLE SCOTT.ROW_MIG
  2  MOVE TABLESPACE TOOLS;


1. 테이블의 재구성

2. 특정 TABLESPACE로 이동

또 이런 명령은 EXPORT/IMPORT라는 툴로도 사용할수있다.


DATATYPE


NUMBER

VARCHAR2(4000) -> LONG(2G)/LONG RAW -> LOB :  CLOB,BLOB,BFILE

DATA


SQL> CREATE TABLE UK
  2  (A1 LONG,
  3  A2 LONG);
A2 LONG)
*
3행에 오류:
ORA-01754: LONG 유형의 열은 테이블에 1 개만 포함될 수 있습니다



SQL> CREATE TABLE UK
  2  (A1 CLOB,
  3  A2 BLOB,
  4  A3 BFILE);

테이블이 생성되었습니다.

LONG은 지난 구버전의 호한성을 위해 남겨졌다.


SQL> ALTER UK MOVIE TABLESPACE TOOLS;실행불가

테이블에 LOG,LOG가 하나도 있으면 실행이안되며 EXPORT/INPUT으로  결정된다.

;



INDEX 모습

 

O(OBJECT)F(FILE)B(BLOCK)R(ROW)=OFBR=>6.3.6.3 =>주소


SQL> SELECT ROWID,EMPNO
  2  FROM EMP
  3  WHERE ROWID='AAAHZ6AABAAAMUSAAI';

ROWID                   EMPNO
------------------ ----------
AAAHZ6AABAAAMUSAAI       7839
트리구조로 되어 있다. TABLE과 별도의 저장 장소를 사용하고있따.(B*TREE (BALANCE TREE))



INDEX의 구조


INDEX를 쓰면 SELECT 속도는향상되고 DML은 떨어진다.

 

TABLE , ROW의 크기가 클때 유리하다

자주검색에사용되는 COLUMN에 사용하면 유리하다.

JOIN CORDITION에 사용되는 COLUMN에 사용하면 유리하다.

NULL을 많이 포함 하는 컬럼에 사용하면 유리하다.

분포도가 고른 TABLE에 유리하다.

 

AUTO : PK ,UK 자동으로 생성된다.



SQL> ALTER TABLE EMP
  2  ADD CONSTRAINT EMP_EMPNO_PK PRIMARY KEY(EMPNO);

테이블이 변경되었습니다.

SQL> --DESC USER_INDEXES
SQL> DESC USER_INDEXES
 이름                                      널?      유형
 ----------------------------------------- -------- ----------------------------
 INDEX_NAME                                NOT NULL VARCHAR2(30)
 INDEX_TYPE                                         VARCHAR2(27)


SQL> SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS
  2  FROM USER_INDEXES
  3  WHERE TABLE_NAME = 'EMP';

INDEX_NAME                     INDEX_TYPE                  UNIQUENES
------------------------------ --------------------------- ---------
EMP_EMPNO_PK                   NORMAL                      UNIQUE


오라클이 제약을 주면 자동으로 인덱스가 생성된다.



그외 일반 인덱스는...

SQL> SELECT EMPNO, ENAME, SAL
  2  FROM EMP
  3  WHERE ENAME = 'SCOTT';

     EMPNO ENAME             SAL
---------- ---------- ----------
      7788 SCOTT            3000

SQL> SELECT INDEX_NAME ,  INDEX_TYPE, UNIQUENESS
  2  FROM USER_INDEXES
  3  WHERE TABLE_NAME = 'EMP';

INDEX_NAME                     INDEX_TYPE                  UNIQUENES
------------------------------ --------------------------- ---------
EMP_EMPNO_PK                   NORMAL                      NONUNIQUE

PK_EMP                                NORMAL                      UNIQUE



ADMIN때부터는 INDEX도 SEGMENT라고 한다 . 추가하는 옵션이 더있다.


SQL> CREATE INDEX IDX_EMP_JOB
  2  ON EMP(JOB)
  3  TABLESPACE INDX
  4  STORAGE
  5     (INITIAL        64K
  6     NEXT            64K
  7     MINEXTENTS      2
  8     MAXEXTENTS      100
  9     PCTINCREASE     50)
 10  INITRANS 5         MAXTRANS 100
 11  LOGGING;

인덱스가 생성되었습니다.


T3 (테이블 물리적 블락)

ID        |      NAME

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

123      |       ABC   ---> |체인정보|락|2|4|123_|3|ABC|  ---INDEX

           |       DEF   ---> |체인정보|락|2|0|3|DEF|

456      |                ---> |체인정보|락|2|4|456_|


CREATE INDEX IDX_T3_ID ON T3(ID,NAME); (SINGLE INDEX, 결합 INDEX)


ID        |      NAME

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

123      |       ABC   ---> |락|1|4|123_|ROWID

           |       DEF   --->              X

456      |                ---> |락|1|4|456_|ROWID|




인덱스의 특징

 

SELECT * FROM EMP WHERE JOB IS NULL;

JOB컬럼에 인덱스를 만들어 놓고 문장을 실행하면 인덱스를 사용하지 않았을까?

-> NULL은 인덱스의 대한 값을 가지고 있지 않다.

 

테이블에 명령을 하면 인덱스에서도 명령이 일어난다.(INSERT, DELETE)

UPDATE EMP SET EMPNO = 102 WHERE EMPNO = 26;

명령어를 실행하면 물리적으로 테이블과 인덱스에 UPDATE가 일어나고...

SELECT 실행하면...

SELECT * FROM EMP WHRER EMPNO =102;

똑같이 값을 업데이트하면 못찾아간다.(인덱스는 정렬을 해야된다.)

그러므로 인덱스는 DELETE AND INSERT가 되어야 된다.

 

PCTFREE 업데이트 할려고 할때 공간이 부족하면 ROW가 MIGRATION이일어난다.

             그걸 대비해서 예비 공간을 만들어 놓은것.(테이블)

             인덱스에는 PCTFREE는 필요가 없다.

PCTUSED 는 항상 0 이다.

항상 인덱스는 항상 범위값이 있다. 인덱스의 리프블락에서는 한건에 데이터가 있더라도

범위밖에 데이터는 올수없다. 범위밖에 값이 들어올려면 데이타를 다 삭제하고 다시 ..ㄷㄷ;

 

인덱스가 필요에따라 데이터가 한곳에만 집중해서 들어오면 저장을 할수가 없다.

그러면 또다른 블락으로 SPILIT? 나눠진다.

인덱스에 블락을 꽉꽉채워두면 데이터가 들어올때마다 나눠진다.

그래서 필요한게 블락내에 비어있는 공간이 필요하다.

그럼 PCTFREE를 다시 사용하게된다.

인덱스에서 PCTFREE의 의미는 FREE FOR INSERT다.(인서트를 위한 예약공간의 의미)

 

SQL> SHOW USER
USER은 "SCOTT"입니다
SQL> CREATE INDEX IDX_EMP_SAL
  2  ON EMP(SAL)
  3  PCTFREE 20
  4  SORT;

인덱스가 생성되었습니다.

 

SQL> CREATE TABLE K1
  2  (ID NUMBER);

테이블이 생성되었습니다.

SQL> INSERT INTO K1 VALUES(1);

1 개의 행이 만들어졌습니다.

SQL> INSERT INTO K1 VALUES(2);

1 개의 행이 만들어졌습니다.

SQL> INSERT INTO K1 VALUES(3);

1 개의 행이 만들어졌습니다.

SQL> CREATE INDEX IDX_K1_ID
  2  ON K1(ID)
  3  NOSORT;

인덱스가 생성되었습니다.


SQL> CREATE INDEX IDX_K1_ID
  2  ON K1(ID)
  3  NOSORT;
ON K1(ID)
   *
2행에 오류:
ORA-01409: NOSORT 옵션은 사용할 수 없습니다 행이 오름차순으로 되어 있지
않습니다

 

'Programing > Oracle' 카테고리의 다른 글

Oracle - Listener  (0) 2008.07.29
Oracle - network  (0) 2008.07.29
Oracle -  (0) 2008.07.29
Oracle - USER TABLE  (0) 2008.07.29
Oracle - Group  (0) 2008.07.29