SELECT A.ORDER_ID,
       A.ORDER_DATE,
       A.ORDER_MODE ,
       C.FIRST_NAME EMPNAME,
       D.CUST_FIRST_NAME ,
       B.PRODUCT_ID,
       B.UNIT_PRICE,
       B.QUANTITY
  FROM ORDERS A,
       ORDER_ITEMS B,
       EMPLOYEES C,
       CUSTOMERS D
 WHERE A.ORDER_ID = B.ORDER_ID
   AND A.EMPLOYEE_ID = C.EMPLOYEE_ID
   AND A.CUSTOMER_ID = D.CUSTOMER_ID
   AND A.ORDER_DATE >= TO_DATE('20120101', 'YYYYMMDD')
   AND A.ORDER_DATE < TO_DATE('20120102', 'YYYYMMDD') ;


alter session set statistics_level=all;
select * from table(dbms_xplan.display_cursor(null, null, 'allstats last'));
select * from table(dbms_xplan.display_cursor(null, null, 'allstats last advanced'));

* ORDER_ITEM을보면 E-Rows가 29M으로 많이 조회된다


--사전 분석
select TABLE_NAME, COLUMN_NAME, DATA_TYPE, NUM_DISTINCT
  from dba_tab_columns
 where TABLE_NAME IN ('ORDER_ITEMS','ORDERS','CUSTOMERS','EMPLOYEES') 
   and NUM_DISTINCT > 0
 order by NUM_DISTINCT DESC;

create index IDX_ORDITEM_ORDID on order_items(ORDER_ID);

* A-Time이나 Buffer등 확 줄은 것을 확인할 수 있다.

-- 순서 지정
순서 힌트 지정 이유는 옵티마이저가 설정한 최적실행 경로 순서를 힌트로 줌으로써 혹시 나중에 실행 순서가 바뀌더라도 이전의 실행순서를 따르게 하기 위함
SELECT /*+ LEADING (A, C, D, B) */
       A.ORDER_ID,
       A.ORDER_DATE,
       A.ORDER_MODE ,
       C.FIRST_NAME EMPNAME,
       D.CUST_FIRST_NAME ,
       B.PRODUCT_ID,
       B.UNIT_PRICE,
       B.QUANTITY
  FROM ORDERS A,
       ORDER_ITEMS B,
       EMPLOYEES C,
       CUSTOMERS D
 WHERE A.ORDER_ID = B.ORDER_ID
   AND A.EMPLOYEE_ID = C.EMPLOYEE_ID
   AND A.CUSTOMER_ID = D.CUSTOMER_ID
   AND A.ORDER_DATE >= TO_DATE('20120101', 'YYYYMMDD')
   AND A.ORDER_DATE < TO_DATE('20120102', 'YYYYMMDD') ;

파티션 테이블(partition table)

 

파티션 테이블 설계

대용량 테이블의 성능저하를 방지하고 관리를 수월하게 하고자 파티션 테이블을 고려할 수 있는데, 서로 다른 파티션에 데이터를 저장함으로써 노드 간의 디스크 경합을 최소화하여 성능을 향상한다.

 

 파티션 테이블의 장단점

 장점

 - 디스크 장애시 해당 파티션만 영향을 받으므로 데이터의 훼손 가능성이 감소하고 가용성이 향상

 - 개별 Partition 단위의 관리가 가능 (DML, Load, Import, Export, Exchange 등)

 - 조인시 파티션 간의 병렬 처리 및 파티션 내에서의 병렬 처리를 수행  

 - 데이터 액세스 범위를 줄여 성능을 향상 시키고 테이블의 파티션 단위로 디스크의 I/O를 분산해 부하를 감소

 단점

 - 파티션 키 값 변경에 대한 별도 관리 필요 ( 관리가 불편 )

 - 파티션에 기준이 되는 것이 컬럼의 일부일 때 일부를 기준으로 파티션을 구성할 수 없으므로 이에 해당하는 오버헤드 컬럼이 있어야 함.

 

 파티션의 종류와 특징

파티션 종류 

내용 

 RANGE

 - 일, 월, 분기 등 특정 컬럼의 정렬 값을 기준으로 분할하는 방식으로 논리적인 범위의 분산에 효율적
 - 관리가 용이하며 이력 데이터에 적합
 - 파티션을 결정하는 컬럼을 명시하여야 하며 MAXVALUE값은 NULL값을 포함
 - 범위가 포함하는 데이터의 양이 일정하지 않은 경우 특정 파티션에 대해 데이터가 편중될 수 있음

 HASH

 - 데이터의 균등 분할을 통해 성능을 향상 시키고자 하는 경우에 효율적
 - 파티션 키에 해시함수를 적용한 결과 값이 같은 레코드를 같은 파티션 세그먼트에 저장해 두는 방식
 - Row와 파티션 간의 매핑을 사용자가 제어할 수 없음
 - 파티션 키의 해시 값에 의해 데이터가 다수의 파티션에 분배되며 균등한 분배를 위해서는 파티션 개수를

  명시하여야 하며 파티션의 수는 2의 거듭제곱의 수로 지정
 - NULL값은 첫 번째 파티션에 위치함
 - 고객ID처럼 변별력이 좋고 데이터 분포가 고른 컬럼을 파티션 키 컬럼으로 선정해야 효과적

 LIST

 -  파티션 컬럼을 명시, 키 컬럼 값을 기준으로 파티션하는 방식 컬럼의 구체적인 값들에 대해 파티션을 명확하게

   컨트롤하고자 할 때 효율적
 -  연관되지 않은 데이터, 순서에 맞지 않는 데이터의 그루핑을 쉽게 할 수 있음
 -  명시되지 않은 값을 가진 Row는 Insert가 불가능
 -  여러 컬럼으로 파티션 키를 생성할 수 없고 오직 하나의 컬럼만 가능
 -  각 파티션에 대해 모든 파티션 키는 반드시 문자로 LIST 되어야 하며 파티션값의 List는 4K까지 가능
 -  파티션 키의 값은 64K-1을 초과할 수 없고 NULL 값을 포함한 어떠한 값이라도 한 번만 명시 가능

 COMPOSITE

 - Range + List, Range + Hash 파티션 등의 조합으로 구성
 - 이력 데이터와 온라인 데이터의 복합적인 성격을 지닌 데이터의 분할에 용이하며 병렬 DML 작업에 뛰어난

  수행성능을 보장
 - 파티션 및 서브 파티션 단위의 관리 작업 수행이 가능
 - Hash 파티셔닝의 경우 스토리지 스트라이핑으로 인해 디스크 점핑이 발생할 수 있으므로 충분한 검토 후 적용

 INTERVAL

 - RANGE 파티셔닝과 유사하며 파티션이 추가되는 규칙을 지정하는 방식
 - 기존 파티션에 데이터가 있고 새로운 데이터가 입력될 때에만 새로운 파티션을 생성함
 - RANGE 파티션에서 MAXVALUE 파티션 없이 생성 후 데이터가 추가되면 지정된 INTERVAL 만큼 늘어난

   범위를 가지는 파티션이 생성됨

 REFERENCE

 - 자식 테이블 파티션이 부모 테이블 파티션과 일대일 관계인 환경에서 자식테이블을 파티션할 때 적용
 - 기본 키 – 외래 키 관계를 통해 자식 테이블의 파티셔닝을 부모 테이블로부터 상속
 - 파티셔닝 키는 자식 테이블의 실제 컬럼에 저장되지 않음

* RANGE > LIST > HASH 순으로 많이씀

 

 

 테이블 선정 조건

 - 일부 데이터가 손상되더라도 나머지 데이터 사용이 가능해야 하는 테이블

 - 복구를 최대한 빨리 적용해야 하는 테이블

 - 테이블을 크기가 큰 경우

 

 파티션 키 선정 조건

   데이터가 어떤 파티션에 저장되는지 알 수 있는 Range Partitioning을 사용하는 것이 Hash Partitioning을 사용하는 경우에 비해

   관리측면에서 유리한 점이 많다. Range Partitioning 에서의 Load Balancing은 파티션 키에 의존하므로 파티션 키 선정시 이를 고려해야 함.

   여러 파티션에 대한 조회는 한 테이블로 구성하였을 경우보다 떨어진다. 따라서 파티션으로 구성하였을 경우 파티션의 기준이되는 키를 잘 구성해야한다

 

   - Primary Key 혹은 Primary Key의 첫번째 컬럼  -- > * 파티셔닝 의미없음

   - 매일 생성되는 날짜 컬럼

   - 백업 기준이 되는 날짜 컬럼

   - 자주 조인이 일어나는 테이블의 Foreign Key

   - Partition간 이동이 없는 컬럼

   - OLTP에서 자주 SQL구문에서 사용되는 컬럼

   - I/O 병목을 줄일 수 있는 데이터 분포도가 양호한 컬럼

 

 파티션 개수 결정

  - 검색조건에서 Composite Primary Key의 일부분만을 사용할 경우 Partition의 개수가 적은 것이 속도가 더빠름

    그러나 Composite Primary Key의 전체를 사용할 경우는 Partition 의 개수가 많은 것이 속도가 더 빠름

  - Batch, OLAP 작업일 경우는 partition 개수가 적은 거이, OLTP작업일 경우는 Partition 개수가 많은 것이  Performance가 더 우수

  - 실제 테이블을 구성함에 있어 Partition의 개수가 너무 적을 경우 Partition효과를 볼수 없게 되고 너무 많을 경우 각 Partition의 value range를

   체크 하므로 parsing time이 길어지고 관리대상이 많아지는 단점이 있음.

 

 

RANGE PARTITION

--업무 쿼리(예를들어 업무때 사용하는 쿼리가 이렇다 치면)
select order_id, product_id
 from ORDER_ITEMS
where to_char(order_date,'yyyymm') between 200801 and 2000804;

* 결과가 너무 많이 나와 관리하기 불편하다.

이때 파티션을 나눠 관리하며 보통 월단위로 많이 나눈다.

 

select * from order_items;

select /*+ parallel(a 16) */ to_char(order_date, 'yyyy'), count(*)
  from order_items a
 group by to_char(order_date, 'yyyy')
 order by to_char(order_date, 'yyyy');

 

--가상컬럼 추가하여 테이블생성
 create table order_item_pt_rg (
    ORDER_ID    VARCHAR2(17),
    PRODUCT_ID  VARCHAR2(7),
    ORDER_DATE  DATE,
    UNIT_PRICE  NUMBER,
    QUANTITY    NUMBER,
    NEW_ORDER_DATE VARCHAR2(10) GENERATED ALWAYS AS (to_char(order_date, 'yyyymm'))
)
tablespace users
partition by range(NEW_ORDER_DATE) (
partition p2007 values less than('20080101'),
partition p2008 values less than('20090101'),
partition p2009 values less than('20100101'),
partition p2010 values less than('20110101'),
partition p2011 values less than('20120101'),
partition p2012 values less than('20130101'),
partition pmax  values less than(maxvalue)
);

 

-- DATA INSERT
ALTER TABLE order_item_pt_rg NOLOGGING; -- 빠른 INSERT를 위해 설정

INSERT INTO order_item_pt_rg
SELECT * FROM ORDER_ITEMS;
-- ORA - 00947 : 값의 수가 충분하지 않습니다. 발생
-- ( 컬럼 수가 맞지 않아서 발생 )

INSERT /*+ PARALLEL (A 4) APPEND */    -- NOLOGGING 일때 INSERT할때 APPEND하는게 좋음
  INTO order_item_pt_rg A (ORDER_ID,
                           PRODUCT_ID,
                           ORDER_DATE,
                           UNIT_PRICE,
                           QUANTITY)
SELECT /*+ PARALLEL (B 4) */ *
  FROM ORDER_ITEMS B;

 

-- 데이터 조회
desc order_items;

 

select /*+ PARALLEL (A 4) */ sum(QUANTITY)
  FROM ORDER_ITEMS A
 WHERE TO_CHAR(ORDER_DATE,'YYYY') BETWEEN '2008' AND '2009';

 

 

SELECT /*+ PARALLEL (A 4) */ sum(QUANTITY)
  FROM ORDER_ITEMS A
 WHERE NEW_ORDER_DATE BETWEEN TO_DATE(2008,'YYYY') AND TO_DATE(2009,'YYYY');
 
alter session set statistics_level=all;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
select * from table(dbms_xplan.display_cursor(null,null,'allstats last advanced'))

 

PARTITION ADMIN

-- 파티션 별 DML
SELECT * FROM order_item_pt_rg PARTITION (P2007);

INSERT INTO order_item_pt_rg PARTITION (PMAX)
(ORDER_ID,PRODUCT_ID,ORDER_DATE, UNIT_PRICE, QUANTITY)
VALUES ('C00150235','C084', SYSDATE, 999, 9);

 

-- PARTITION에 맞지 않는 데이터 INSERT
INSERT INTO ORDER_ITEM_PT_RG PARTITION (PMAX)
(ORDER_ID,PRODUCT_ID,ORDER_DATE, UNIT_PRICE, QUANTITY)
VALUES ('C00150235','C084', TO_DATE(201101,'YYYYMM'), 999, 9);
-- ORA-14401:삽입된 분할영역 키는 지정된 분할영역의 밖에 있습니다.
-- 키 값이 맞지 않아 INSERT 불가능

 

-- KEY COLUMN UPDATE
UPDATE order_item_pt_rg
   SET ORDER_DATE = SYSDATE
 WHERE PRODUCT_ID='P183';   -- 2008년 데이터
 -- ORA-14402 : 분할영역 키 열을 수정하는것은 분할영역 변경이 생깁니다.
 
SELECT TABLE_NAME,ROW_MOVEMENT
  FROM DBA_TABLES
 WHERE TABLE_NAME='ORDER_ITEM_PT_RG';

 

TABLE_NAME           ROW_MOVE
-------------------- --------
ORDER_ITEM_PT_RG  DISABLED

 

-- ROW MOVEMENT ENABLE
ALTER TABLE ORDER_ITEM_PT_RG ENABLE ROW MOVEMENT;
ALTER TABLE ORDER_ITEM_PT_RG DISABLE ROW MOVEMENT;

 

 

-- PARTITION DROP
ALTER TABLE ORDER_ITEM_PT_RG DROP partition p2007;

 

SELECT * FROM DBA_TAB_PARTITIONS
WHERE TABLE_NAME='ORDER_ITEM_PT_RG'

 

 

-- PARTITION SPLIT
ALTER TABLE ORDER_ITEM_PT_RG SPLIT partition PMAX
AT ('20140101')
INTO ( PARTITION P2013, PARTITION PMAX);

 

INSERT INTO ORDER_ITEM_PT_RG
(ORDER_ID, PRODUCT_ID, ORDER_DATE, UNIT_PRICE, QUANTITY)
VALUES ('AAAA','H111',TO_DATE(201311,'YYYYMM'),1,1);


commit;

 

SELECT * FROM ORDER_ITEM_PT_RG PARTITION(P2013);

 

 

 

 

-- PARTITION ADD
ALTER TABLE ORDER_ITEM_PT_RG ADD partition
p2013 values less than('20140101');
* ADD하는 FORM은 이게 맞지만 현재 구성은 PMAX로 해놓아서 추가가 되지 않음 --> SPLIT 해야함

 

-- PARTITION ADD
ALTER TABLE ORDER_ITEM_PT_RG ADD partition
p2013 values less than('20140101');

 

HASH PARTITION

SELECT * FROM DBA_DATA_FILES;

CREATE TABLESPACE TBS1 DATAFILE
'/oracle11/app/oradata/testdb/tbs1.dbf' SIZE 100M AUTOEXTEND ON;

CREATE TABLESPACE TBS2 DATAFILE
'/oracle11/app/oradata/testdb/tbs2.dbf' SIZE 100M AUTOEXTEND ON;

CREATE TABLESPACE TBS3 DATAFILE
'/oracle11/app/oradata/testdb/tbs3.dbf' SIZE 100M AUTOEXTEND ON;

CREATE TABLESPACE TBS4 DATAFILE
'/oracle11/app/oradata/testdb/tbs4.dbf' SIZE 100M AUTOEXTEND ON;

alter user system quota unlimited on tbs1;
alter user system quota unlimited on tbs2;
alter user system quota unlimited on tbs3;
alter user system quota unlimited on tbs4;

 

-- CRAETE TABLE PARTITION 이름이 랜덤 설정 ( 아래 그림 참조 )

CREATE TABLE CUSTOMERS_PT_HS
(
    CUSTOMER_ID     VARCHAR2(11),
    CUST_FIRST_NAME VARCHAR2(20) NOT NULL,
    CUST_LAST_NAME  VARCHAR2(20) NOT NULL,
    EMAIL           VARCHAR2(92),
    BIRTHDAY        DATE,
    PHONE_NUMBER    VARCHAR2(325),
    GENDER          VARCHAR2(1),
    WEDDING_TYPE    VARCHAR2(1),
    CUST_JOB_NAME   VARCHAR2(12)
)
PARTITION BY HASH(CUSTOMER_ID)
PARTITIONS 4
STORE IN (TBS1, TBS2, TBS3, TBS4);

 

-- 파티션 이름을 설정하면서 CRATE TABLE

CREATE TABLE CUSTOMERS_PT_HS2
(
    CUSTOMER_ID     VARCHAR2(11),
    CUST_FIRST_NAME VARCHAR2(20) NOT NULL,
    CUST_LAST_NAME  VARCHAR2(20) NOT NULL,
    EMAIL           VARCHAR2(92),
    BIRTHDAY        DATE,
    PHONE_NUMBER    VARCHAR2(325),
    GENDER          VARCHAR2(1),
    WEDDING_TYPE    VARCHAR2(1),
    CUST_JOB_NAME   VARCHAR2(12)
)
PARTITION BY HASH(CUSTOMER_ID)
(PARTITION P1 TABLESPACE TBS1,
 PARTITION P2 TABLESPACE TBS2,
 PARTITION P3 TABLESPACE TBS3,
 PARTITION P4 TABLESPACE TBS4
 );
 
 SELECT * FROM DBA_SEGMENTS
 WHERE SEGMENT_NAME LIKE 'CUSTOMERS_PT%'
   AND OWNER ='SYSTEM';
 


INSERT /*+ PARALLEL(A 4) APPEND */ INTO CUSTOMERS_PT_HS2 A
SELECT /*+ PARALLEL(B 4) */ * FROM CUSTOMERS B;

COMMIT;

SELECT * FROM CUSTOMERS_PT_HS2 PARTITION(P1);
-- 어떤 기준으로 나눠진지는 모르겠음

 

LIST PARTITION

-- list partition table 생성

CREATE TABLE LOCATIONS_PT_LI
(
    LOCATION_ID     NUMBER(4),
    STREET_ADDRESS  VARCHAR2(40),
    POSTAL_CODE     VARCHAR2(12),
    CITY            VARCHAR2(30) CONSTRAINT LOC_CITY_NN CHECK ("CITY" IS NOT NULL),
    STATE_PROVINCE  VARCHAR2(25),
    COUNTRY_ID      CHAR(2)
)
    PARTITION BY LIST (STATE_PROVINCE)
    (PARTITION REGION_EAST VALUES ('MA','NY','CT','NH','MD','VA','PA','NJ')
    TABLESPACE TBS1,
    PARTITION REGION_WEST VALUES ('CA','AZ','NM','OR','WA','UT','NV','CO')
    TABLESPACE TBS2,
    PARTITION REGION_SOUTH VALUES ('TX','KY','TN','LA','MS','AR','AL','GA')
    TABLESPACE TBS3,
    PARTITION REGION_CENTRAL VALUES ('OH','ND','SD','MO','IL','MI','IA',NULL)
    TABLESPACE TBS4,
    PARTITION EXTRA VALUES (DEFAULT) TABLESPACE USERS
    );

insert into LOCATIONS_PT_LI
select * from hr.LOCATIONS

 

COMMIT;

 

SELECT * FROM LOCATIONS_PT_LI PARTITION(EXTRA);

* 조건에 맞게 PARTITION이 나눠짐

'Study Note > Database' 카테고리의 다른 글

파티션 테이블(partition table) - 인덱스(index)  (0) 2016.02.25
SQL TUNNING - 1  (0) 2016.02.24
Index Organized Table (IOT)  (0) 2016.02.23
Index 생성 속도 향상 - parallel, nologging 옵션  (0) 2016.02.23
V$SQLAREA 자료 사전  (0) 2016.02.16

Index Organized Table (IOT)

□ Index Organized Table (IOT) 의 특성

  - B*Tree 구조에 전체 행 저장

    · 저장 공간 감소 (인덱스와 데이터 블록 공유)

  - Primary Key를 기준으로 테이블 데이터를 읽을 때 빠른 성능 제공

  - 논리적 ROWID 개념 지원

    · IOT내의 ROW를 지칭할 수 있는 논리적 ID

    · 2차 인덱스의 생성 및 사용이 가능

  - 읽기 전용 데이터에 적합

    · UPDATE가 자주 일어나는 경우, 인덱스 구조에 큰 변화 발생

 

 

-- IOT 테이블
CREATE TABLE TEST(
 NO NUMBER  CONSTRAINT TEST_NO_PK Primary Key,
 TITLE VARCHAR2(50),
 CONTNETS VARCHAR2(500)

)
 TABLESPACE USERS;
 
INSERT INTO TEST VALUES(3,'CCCC','CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC');
INSERT INTO TEST VALUES(1,'AAAA','AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
INSERT INTO TEST VALUES(5,'EEEE','EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE');
INSERT INTO TEST VALUES(2,'BBBB','BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB');
INSERT INTO TEST VALUES(4,'DDDD','DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD');
COMMIT;

 

CREATE TABLE IOTTEST (
NO NUMBER CONSTRAINT IOTTEST_PK_NO PRIMARY KEY,
TITLE VARCHAR2(50),
CONTENTS VARCHAR2(500)

)
ORGANIZATION INDEX TABLESPACE USERS
PCTTHRESHOLD 40 INCLUDING TITLE
OVERFLOW TABLESPACE USERS;

 
INSERT INTO IOTTEST VALUES(3,'CCCC','CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC');
INSERT INTO IOTTEST VALUES(1,'AAAA','AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
INSERT INTO IOTTEST VALUES(5,'EEEE','EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE');
INSERT INTO IOTTEST VALUES(2,'BBBB','BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB');
INSERT INTO IOTTEST VALUES(4,'DDDD','DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD');
COMMIT;


select no, title from test'


select no, title from iottest; 

 

--조회해보면 IOTTEST는 테이블이 없고 인덱스만 나온다.
select * from DBA_SEGMENTS
WHERE SEGMENT_NAME LIKE '%TEST%';.

select * from DBA_SEGMENTS
WHERE SEGMENT_NAME LIKE '%IOT%'
and TABLESPACE_NAME='USERS';

 

- ORGANIZATION INDEX TABLESPACE : IOT Data가 저장되는 Tablespace
- PCTTHRESHOLD(default : 50) : IOT를 위해서 예약된 공간의 백분율로,
  1블럭의 N% 비율보다 큰 데이터가 입력되면 키 열이 아닌 데이터는
  OVERFLOW TABLESPACE절에 정의된 테이블스페이스에 저장

- INCLUDING : IOT 행을 인덱스와 오버플로우 구역으로 나눌 열을 구분
  INCLUDING 뒤에 있는 컬럼만 제외하고 모두 오버플로우 세그먼트에 저장
  INCLUDING이 지정되지 않았는데 행 크기가 PCTTHRESHOLD를 초과하면
  기본 키 열을 제외한 모든 이 오버플로우 세그먼트에 저장
 
- OVERFLOW TABLESPACE : PCTTHRESHOLD를 초과하는 Data 행이 저장


 

'Study Note > Database' 카테고리의 다른 글

SQL TUNNING - 1  (0) 2016.02.24
파티션 테이블(partition table)  (0) 2016.02.24
Index 생성 속도 향상 - parallel, nologging 옵션  (0) 2016.02.23
V$SQLAREA 자료 사전  (0) 2016.02.16
SQL*TRACE  (0) 2016.02.16

Index 생성 속도 향상 - parallel, nologging 옵션

parallel processing을 적용함으로 써 인덱스 생성 속도를 올릴 수 있다.

또 인덱스 생성 시 log가 생기는데 이것은 시스템 부하를 발생시킬 우려가 있다. log를 안남기게 nologging 옵션을 주게 되면

index생성 속도를 더욱 향상시킬 수 있다.

 

SQL> create index emp_idx

      on emp(ename)

      nologging

      parallel 8;

 

주의

index 생성 후 logging mode와 parallel을 원상태로 돌려줘야함

 

SQL> alter index emp_idx logging;

SQL> alter index emp_idx parallel 1;

 

==> 이 설정을 무시하게 되면 이 index를 사용하는 쿼리는 조회시 parallel로 수행하게 되서

     시스템에 부하가 올 수 있다.

'Study Note > Database' 카테고리의 다른 글

파티션 테이블(partition table)  (0) 2016.02.24
Index Organized Table (IOT)  (0) 2016.02.23
V$SQLAREA 자료 사전  (0) 2016.02.16
SQL*TRACE  (0) 2016.02.16
DBMS_XPLAN.DISPLAY 다량데이터 조회시 참고사항  (0) 2016.02.16

V$SQLAREA 자료 사전

공유 - 폴 영역의 구문분석 결과를 제공

 ∙ 가장 많은 Disk-I/O가 발생한 SQL문을 제공

 ∙ 가장 많은 메모리를 사용한 SQL문을 제공

 ∙ 가장 많은 CPU 사용시간이 소요된 SQL문을 제공

 ∙ 사용자가 실행한 SQL문의 패턴 제공

 ∙ SORT 횟수, INVALIDATIONSQL문 제공

 

V$SQLAREA 결과 분석

SQL_TEXT

VERSION_COUNT

LOADS

INVALIDATIONS

PARSE_CALLS

SORT

SELECT * FROM DEPT

1

1

0

1

0

SELECT * FROM dept

1

1

1

1

0

SELECT * FROM DEPT ORDER BY 1

1

1

0

3

1

1) version_count : 같은 사용자가 실행하면 같은 version count 이지만 다른 사용자이면 count가 증가

2) load : Parsing SQL문이 library cache 영역에 저장된 횟수

3) invalidation : Parsing후 로더된 SQL문에서 참조된 테이블이 ALTER, DROP, ANALYZE되면

Parsing 정보를 재사용 할 수 없다

4) parse_call : 최초 Parsing후 재사용된 횟수

 

* 동일한 문장이 아닌 경우

1. 사용자 계정이 다르면 동일한 문장이 아님

2. SPACE의 개수가 틀리면 동일한 문장이 아님

3. 바인드 변수명 또는 변수의 데이터 타입이 틀려도 다른 문장

4. ,소문자가 틀려도 다른 문장

5. 라인, 들여쓰기 등이 틀려도 다른 문장

 

* 동일한 SQL문의 작성 지침

1. SQL문의 대문자 또는 소문자를 통일

2. 변수명은 SQL, 객체명, 변수명과 구분하기 위해 소문자로 작성

3. 다른 스키마의 테이블을 호출할 때는 "SCHEMA.테이블명작성

4. SQL문의 각 단어의 여백은 한 칸으로

5. SQL문의 내의 변수명은 변수 선언 기준 안에 따르며 해당 컬럼명을 접두어와 결합하여 사용

6. SQL문의 SELECT, FROM, WHERE절은 라인의 선두에 기술

'Study Note > Database' 카테고리의 다른 글

Index Organized Table (IOT)  (0) 2016.02.23
Index 생성 속도 향상 - parallel, nologging 옵션  (0) 2016.02.23
SQL*TRACE  (0) 2016.02.16
DBMS_XPLAN.DISPLAY 다량데이터 조회시 참고사항  (0) 2016.02.16
SQL TUNING - 기본  (0) 2016.02.15

SQL*TRACE

 

SQL*TRACE 기능

EXPLAIN PLAN 명령어와 함께 튜닝작업 시 자주 사용되는 기능

사용자가 실행한 SQL문에 대한 실행계획 만을 보여주는 EXPLAIN PLAN과는 달리 SQL*Trace 기능은

   SQL문의 실행계획과 더불어 실행 소요시간과 디스크 및 메모리부터 읽은 블록 수에 대한 정보도 포함

SQL*TRACE 기능에 의해 분석되는 결과는 운영체제 상에 생성

이 파일은 바이너리 형태이기 때문에 사용자가 직접 눈으로 확인할 수 없음

TKPROF 유틸리티를 사용하여 텍스트 파일형태로 변화하여 참조

init.ora 파일에 다음과 같은 파라미터 반드시 설정 필요

 

필요 파라미터

1) TIMED_STATISTICS : SQL문의 처리 시간 및 통계정보

2) SQL_TRACE : SQL문의 트레이스 기능을 사용 가능하게 해 주는 파라미터

3) USER_DUMP_DEST : SQL문의 분석된 결과가 저장될 경로를 지정하는 파라미터

4) MAX_DUMP_FILE_SIZE : 분석 결과가 저장될 트레이스 파일의 크기를 결정하는 파라미터

 

-- 파라미터 세팅

alter session set sql_trace=true;

 

-- sql 구문 실행

select * from dept;

 

--확인

select * from v$parameter

where name like 'user_dump%';

 

cd /oracle11/app/diag/rdbms/testdb/testdb/trace

 

$ls -rtl

 

 

가장 최신인 맨 아래 것

-rw-r----- 1 oracle oinstall 1761 Feb 16 14:36 testdb_ora_3913.trc

 

--분석

[oracle@localhost trace]$

tkprof testdb_ora_3913.trc T3913.tkf SYS=NO EXPLAIN=SYSTEM/MANAGER  

 

 

[oracle@localhost trace]$ cat T3913.tkf

 

SQL*TRACE 결과 분석

COUNT : SQL문이 처리될 때 분석, 실행, 인출을 각 몇 번씩 실행 했는지를 나타냄

CPU : SQL문의 처리 단계별로 CPU를 몇 초 사용했는지 나타냄

ELAPSED : SQL문의 처리 단계별로 처리된 소요시간

DISK : 테이블에 저장되어 있는 데이터 파일로부터 데이터를 읽어오기 위해 읽은 블록 수

CUTRRENT : 메모리에 저장된 데이터를 가져오기 위해 읽은 버퍼 블록 수

(현 세션에만 유효한 블록 수 ,주로 의 수행 시)

QUERY : 읽기 일관성을 만족하는 블록 수

 

'Study Note > Database' 카테고리의 다른 글

Index 생성 속도 향상 - parallel, nologging 옵션  (0) 2016.02.23
V$SQLAREA 자료 사전  (0) 2016.02.16
DBMS_XPLAN.DISPLAY 다량데이터 조회시 참고사항  (0) 2016.02.16
SQL TUNING - 기본  (0) 2016.02.15
DDL  (0) 2016.02.04

다량의 데이터를 조회하게 되면

select * from LARGE_EMP;

alter session set statistics_level=all;

select * from table(dbms_xplan.display_cursor(null,null, 'allstats last'));

 

 Orange Tool은

 

데이터의 일부만 표시하게 된다. 이때 Text Output을 확인하면 결과가 다 나오지 않고 나온 일부에 대해서만 분석한다. 

모든 작업의 계획을 보고싶다면  다음 작업을 수행하고 해야 한다.

 

'Study Note > Database' 카테고리의 다른 글

V$SQLAREA 자료 사전  (0) 2016.02.16
SQL*TRACE  (0) 2016.02.16
SQL TUNING - 기본  (0) 2016.02.15
DDL  (0) 2016.02.04
DML  (0) 2016.02.04

-- 튜닝 수업 환경 설정

(대소문자 구분을 끄기위해서 설정)

alter system set sec_case_sensitive_logon=FALSE;

 

ALTER USER SYSTEM IDENTIFIED BY MANAGER;

DROP USER SCOTT CASCADE;

 

CREATE USER SCOTT IDENTIFIED BY TIGER

 

GRANT CONNECT,RESOURCE,DBA TO SCOTT;

 ( pfile일 경우 spfile로 변경 )

 

1. 대용량 샘플 dmp 파일 imp 수행

 

[oracle@localhost ~]$ imp system/MANAGER full=y file=NEW_SCOTT_10.DMP;

 

-- imp 확인 (20table)

SELECT * FROM DBA_TABLES

WHERE OWNER='SCOTT';

 

20 rows selected.

 

-- public synonym 제공

select 'create public synonym '||TABLE_NAME||' for '||OWNER||'.'||TABLE_NAME||';'

from dba_tables

where owner='SCOTT';

 

EXPLAIN PLAN 명령어

 

SQL문의 실행계획과 상태 값을 제공하는 명령어

 

1) 옵티마이저의 유형 (공식기반 또는 비용기반)

2) 옵티마이저에 의해 결정된 실행 계획

3) 실행 계획의 선택 기준(비용계싼 결과 등)

4) SQL문을 실행하면서 사용한 DB구조의 상태 값

- 사용된 데이터버퍼 캐시 블록 수

- 데이터 파일로부터 읽은 블록 수

- 네트워크를 통해 전송된 데이터의 바이트 수

- Sorting 작업 발생 시 사용된 메모리 블록 수

- 처리된 데이터 량

 

SET AUTOTRACE 명령어

 

PLAN_TABLE을 생성 후 한번만 설정해주면 SQL문이 실행될 때 마다 실행계획을 한 화면에 출력

 

 문법

SET AUTOTRACE [ ON | OFF | TRACE | TRACEONLY ]

- ON : SQL문의 실행 결과와 실행계획 그리고 통계정보를 보여주는 옵션

- OFF : 어떤 결과도 보여 주지 않음

- TRACEONLY : 실행계획과 통계정보 만을 보여줌

 

* 켜놨다면 사용후 OFF로 반드시 바꿔줘야함 (조회할때마다 뜨기때문에)

 

SQL> SET AUTOTRACE TRACEONLY;

SQL> SELECT * FROM DEPT;

*

아래부터 올라감

sorts (momory) : PGA ( PGA 사용하다 모자라면 TEMP로 넘어감 )

sorts (disk) : TEMP

 

V$SQL_PLAN

이미 실행된 SQL에 대한 실행계획을 참조할 경우 사용

Shared pool 영역에서 직접 추출된 실행 정보

영원히 보관할 수는 없음

SQL문의 HASH_VALUEADDRESS값을 알아야 함

   => V$SQL, V$SQLAREA에서 참조

-- hash_value, address 찾기

select sql_text

, hash_value

, address

from v$sqlarea

where upper(sql_text) like '%DEPT%'

 

 

 

 select id

, lpad ('', depth) || operation operation

, options

, object_name

, optimizer

, cost

from v$sql_plan

where hash_value = &1

and address = '&2'

start with id = 0

connect by ( prior id = parent_id

and prior hash_value = hash_value

and prior child_number = child_number )

order siblings by id, position;

 

 

결과 분석 (Execution Plan)

SQL> set autotrace traceonly

SQL> select empno, ename, job, sal, dname

from emp, dept

where emp.deptno = dept.deptno;

 

 

SQL> CREATE INDEX DEPTNO_IDX ON EMP(DEPTNO);

= > 다시조회 해도 full scan

* 인덱스를 만들어도 데이터량이 적어서 풀스캔하게됨

 

-- INDEX를 타도록 Hint 설정

select /*+index(emp DEPTNO_IDX) */

empno, ename, job, sal, dname

from emp, dept

where emp.deptno=dept.deptno;

 

 

 

 

 

1) Parsing 단계에서 Data Dictionary로 부터 얻는 테이블의 상태정보 및 통계정보를 참조하기 위해 읽는 블록 수

* 다시 조회하면 줄어듬

2) DML 문이 실행될 때 발생하는 변경 전 데이터를 잠시 저장하기 위한 임시공간

3) SQL문이 실행될 때 디스크 상에 존재하는 테이블 및 인덱스를 저장하기 위한 메모리공간

* 가장 눈여겨 봐야할 튜닝 Point!

4) 데이터가 실제로 존재하는 디스크 상의 데이터 파일로부터 읽혀진 데이터 블록 수

* 다시 조회하면 줄어듬

5) DML문을 실행했을 때 변경 전 데이터와 변경 후 데이터를 로그버퍼 영역에 백업하기 위한 블록 수

6) 클라이언트와 서버 간의 전송된 데이터를 나타냄

* 튜닝 Point가 아님

7) sorting 작업을 위해 사용한 PGA 공간

* sorts (momory) : PGA ( PGA 사용하다 모자라면 TEMP로 넘어감 )

8) sorting 작업을 위해 사용한 TEMP 사용 공간

* sorts (disk) : TEMP

==> 7,8 번이 둘다 많을시 시스템 튜닝을 고려

9) SQL문이 실행된 후 조건을 만족하는 행의 수

* 튜닝 Point가 아님

 

 

 

 

 

※ Update문 기본 튜닝

-- BIG_EMP에도 있는 사원은 COMMSAL에 더해서 LARGE_EMPSALUPDATE 하려고 한다.

-- (SQL구문을 튜닝해서 더 효과적으로 만들기)

 

(튜닝 전)

update large_emp a

set a.sal = ( select b.comm + a.sal

from big_emp b

where b.empno=a.empno);

(튜닝 후)

update large_emp a

set a.sal = a.sal + (select b.comm

from big_emp b

where b.empno=a.empno);

 

 

* consistent gets 천만건 정도 차이나는걸 볼 수 있다

 더 좋은 효과를 위해선 index를 걸어주면 1/4로 주는 걸 볼 수 있다.

'Study Note > Database' 카테고리의 다른 글

SQL*TRACE  (0) 2016.02.16
DBMS_XPLAN.DISPLAY 다량데이터 조회시 참고사항  (0) 2016.02.16
DDL  (0) 2016.02.04
DML  (0) 2016.02.04
[Tool] Orange Character Set 설정하기  (0) 2016.02.04

 

DDL문장과 딕셔너리

 

CREATE

이 명령은 새로운 오브젝트나 스키마를 생성할 때 사용하는 명령어

 

CREATE TABLE 한글테이블

( 컬럼1 NUMBER,

컬럼2 VARCHAR2(10),

컬럼3 DATE );

select * from user_tables

where table_name='한글테이블';

 

 

* 한글로도 테이블명을 선언해서 사용할 수 있음!

 

* 테이블 생성시 테이블명 주의사항

1.반드시 문자로 시작해야함

2. 최대 30byte 한글테이블일 경우 15글자

3. 테이블 한 계정에서 동일 명으로 사용 못함 (다른 계정시 중복가능) 

 

 

 문법예제

CREATE TABLE ddl_test

(no NUMBER(3,1), --3자리인데 한자리는 소수자리 (ex: 10.3)

name VARCHAR2(10), --BYTE

birth DATE [DEFAULT SYSDATE])

TABLESPACE users; --테이블들을 저장하고 있는 단위

 

SELECT * FROM DBA_TABLESPACES;

   

-- SCOTT USERDEFAULT TABLESPACE 확인

SELECT USERNAME, DEFAULT_TABLESPACE

FROM DBA_USERS

WHERE USERNAME='SCOTT';

 

--테이블의 테이블스페이스 확인

SELECT OWNER, TABLE_NAME, TABLESPACE_NAME

FROM DBA_TABLES

WHERE TABLE_NAME='DDL_TEST';

 

--SCOTT 계정의 DEFAULT TABLESPACEEXAMPLE로 변경

ALTER USER SCOTT DEFAULT TABLESPACE EXAMPLE;

 

테이블 복사하기 (CTAS 구문)

CREATE TABLE DEPT3

AS

SELECT * FROM DEPT2;

 

기존 컬럼명 변경후 특정컬럼 가져오기

CREATE TABLE DEPT4

AS

SELECT DCODE AS "DCODE_1",DNAME AS "DNAME_1"

FROM DEPT2;

 

테이블 구조만 생성 (데이터없이)

CREATE TABLE DEPT5

AS

SELECT DCODE,DNAME

FROM DEPT2

WHERE 1=2;

 

 

가상 컬럼 생성(버츄얼컬럼)

CREATE TABLE VT001

( NO1 NUMBER,

NO2 NUMBER,

NO3 NUMBER GENERATED ALWAYS AS (NO1 +NO2) VIRTUAL);

   

DESC VT001;

 

INSERT INTO VT001(NO1,NO2)

VALUES(1,2);

 

SELECT * FROM VT001; 

 

     

--EMP2 테이블의 NAME,BIRTHDAY,PAY을 가지고 GRADE_A, GRADE_B, GRADE_C 테이블을 각각 생성하고

--EMP2 테이블에서 PAY30000000 미만이면 'C', 30000000이상 50000000 이하 'B', 50000000보다 크면 'A'가 되도록 하여

--열 이름을 GRADE로 지정하고 이름, 생일, PAY와 함께 등급별로 테이블을 분류하여 데이터를 INSERT 하여라

 

CREATE TABLE GRADE_A

AS SELECT NAME,BIRTHDAY,PAY,'ABC' AS "GRADE"

FROM EMP2

WHERE 1=2;

 

CREATE TABLE GRADE_B

AS SELECT NAME,BIRTHDAY,PAY,'ABC' AS "GRADE"

FROM EMP2

WHERE 1=2;

 

CREATE TABLE GRADE_C

AS SELECT NAME,BIRTHDAY,PAY,'ABC' AS "GRADE"

FROM EMP2

WHERE 1=2;

 

INSERT ALL

WHEN PAY < 30000000 THEN

INTO GRADE_C VALUES(NAME,BIRTHDAY,PAY,'C')

WHEN PAY BETWEEN 30000000 AND 50000000 THEN

INTO GRADE_B VALUES(NAME,BIRTHDAY,PAY,'B')

WHEN PAY > 50000000 THEN

INTO GRADE_A VALUES(NAME,BIRTHDAY,PAY,'A')

SELECT NAME,BIRTHDAY,PAY

FROM EMP2;

SELECT * FROM GRADE_C;

 

 

--PROFESSOR 테이블에서 홈페이지 주소가 없는 교수들은 ID로 된 홈페이지 주소로 변경하여라

--(홈페이지 주소 : HTTP://WWW.NAVER.COM/ID)

 

SELECT * FROM PROFESSOR;

 

 

 

UPDATE PROFESSOR

SET HPAGE = 'HTTP://WWW.NAVER.COM/'||ID

WHERE HPAGE IS NULL;

 

 

ALTER

CREATE TABLE DEPT6

AS

SELECT DCODE, DNAME

FROM DEPT2

WHERE DCODE IN(1000,1001,1002);

 

-- 디폴트넣은거와 안넣은거의 차이 

ALTER TABLE DEPT6 ADD (LOC VARCHAR2(10));

 

--컬럼 추가시 DEFAULT 설정

ALTER TABLE DEPT6 ADD (LOC2 VARCHAR2(10) DEFAULT 'AAA');

 

--컬럼 추가후 DEFAULT 설정

ALTER TABLE DEPT6 ADD (LOC3 VARCHAR2(10));

ALTER TABLE DEPT6 MODIFY (LOC3 DEFAULT 'BBB');

 

 

SELECT * FROM DEPT6;

 

--CTAS DEPT7 생성 -> ADD COLUMN -> DEPT6 RENAME ;

 

 

--RENAME

ALTER TABLE DEPT6 RENAME COLUMN LOC2 TO AREA;

 

--DEPT6 DEPT7

RENAME DEPT6 TO DEPT7;

 

--컬럼의 데이터 크기를 변경

ALTER TABLE DEPT7 MODIFY (DCODE VARCHAR2(10)); --이미 4크기의 데이터가 들어가 있기 때문에 작게는 변경 불가능

 

DESC DEPT7;

 

SELECT MAX(LENGTH(DCODE)) FROM DEPT7;

 

ALTER TABLE DEPT7 DROP COLUMN LOC3; -- 부하가 걸릴 수 있음 고려

 

SELECT * FROM DEPT7;

읽기 전용 테이블로 변경(읽기 O , 변경 X) [위험!!!!]

10G - 트리거를 사용 OR 제약조건 DISABLE/NOVALIDATE 등을 사용했어야함

 

CREATE TABLE T_READ

(NO NUMBER, NAME VARCHAR2(10));

 

INSERT INTO T_READ

VALUES (1,'AAA');

 

COMMIT;

 

ALTER TABLE T_READ READ ONLY;

 

SELECT TABLE_NAME, READ_ONLY

FROM USER_TABLES

WHERE TABLE_NAME = 'T_READ'

 

(SELECT 만 가능)

 

ALTER TABLE T_READ ADD (TEL NUMBER DEFAULT 111);

ALTER TABLE T_READ MODIFY (NAME VARCHAR2(15)); (UPDATE OPERATION ~~ 오류 뜸)

 

ALTER TABLE T_READ READ WRITE; ( READ ONLY 해제 ) [위험!!!!]

 

DROP TABLE T_READ; [ READ ONLY 상태에서 DROP DROP > READ ONLY ]

 

 

--1) 다음은 웹 사이트의 게시판을 사용하는 회원을 관리하기 위한 테이블 레이아웃이다. 회원테이블(member)을 생성하여라.

 

CREATE TABLE MEMBER2(

USERID VARCHAR2(10),

USERNAME VARCHAR2(10),

PASSWD VARCHAR2(10),

IDNUM VARCHAR2(13),

PHONE NUMBER(13),

ADDRESS VARCHAR2(20),

REGDATE DATE,

INTEREST VARCHAR2(15));

SELECT * FROM MEMBER2;

 

COMMENT ON TABLE MEMBER2 IS '게시판회원테이블';

COMMENT ON COLUMN MEMBER2.USERID IS '사용자아이디';

COMMENT ON COLUMN MEMBER2.USERNAME IS '회원이름';

COMMENT ON COLUMN MEMBER2.PASSWD IS '비밀번호';

COMMENT ON COLUMN MEMBER2.IDNUM IS '주민등록번호';

COMMENT ON COLUMN MEMBER2.PHONE IS '전화번호';

COMMENT ON COLUMN MEMBER2.ADDRESS IS '주소';

COMMENT ON COLUMN MEMBER2.REGDATE IS '가입일';

COMMENT ON COLUMN MEMBER2.INTEREST IS '관심분야';

 

SELECT * FROM USER_TAB_COMMENTS

WHERE TABLE_NAME='MEMBER2';

 

SELECT * FROM USER_COL_COMMENTS

WHERE TABLE_NAME ='MEMBER2';

 

SELECT TABLE_NAME,TABLESPACE_NAME FROM USER_TABLES;

 

--2) 회원테이블에 다음 회원 정보를 입력하여라.

-- (sunshinLee, 이순신, ssl000, 8701011120200, 02)333-2123, 서울, 2015/07/05, 컴퓨터)

 

ALTER SESSION SET NLS_DATE_FORMAT='YYYY/MM/DD'; -- CREATE 문 안에 TO_DATE를 사용하면 부하

 

INSERT INTO MEMBER2(USERID,USERNAME,PASSWD,IDNUM,PHONE,ADDRESS,REGDATE,INTEREST)

VALUES('sunshinLee','이순신','ssl000','8701011120200','023332123','서울', '2015/07/05', '컴퓨터');

 

SELECT PHONE, TO_CHAR(PHONE,'00000000000') FROM MEMBER2;

 

SELECT * FROM MEMBER2;

 

--3) 회원 테이블의 구조와 데이터 집합이 같은 member_second 테이블을 생성하여라.

 

CREATE TABLE MEMBER_SECOND

AS

SELECT * FROM MEMBER2;

 

SELECT * FROM MEMBER_SECOND;

 

--4) 회원 테이블의 userid, username, passwd 컬럼만 복사해서 member_third 테이블을 생성하여라.

 

CREATE TABLE MEMBER_THIRD

AS SELECT USERID,USERNAME,PASSWD FROM MEMBER2;

 

SELECT * FROM MEMBER_THIRD;

 

--5) 회원 테이블과 구조는 동일하고 데이터를 가지지 않는 member_forth 테이블을 생성하여라.

 

CREATE TABLE MEMBER_FORTH

AS SELECT * FROM MEMBER2

WHERE 1=2;

 

SELECT * FROM MEMBER_FORTH;

 

--6) 회원 테이블에 email 컬럼을 추가하여라. , email 컬럼 데이터 타입은 varchar2(50)이다.

ALTER TABLE MEMBER2 ADD(EMAIL VARCHAR2(50));

 

DESC MEMBER2;

 

--7) 회원 테이블에 국적을 나타내는 country 컬럼을 추가하고 기본값을 ‘Korea’로 지정하여라.

ALTER TABLE MEMBER2 ADD(COUNTRY VARCHAR2(10) DEFAULT 'Korea');

/*OR*/ALTER TABLE MEMBER2 MODIFY COUNTRY DEFAULT 'Korea';

 

DESC MEMBER2;

 

--8) 회원 테이블에서 email 컬럼을 삭제하여라.

ALTER TABLE MEMBER2 DROP( EMAIL );

 

DESC MEMBER2;

--9) 회원 테이블의 address 컬럼의 데이터 크기를 30으로 증가시켜라.

ALTER TABLE MEMBER2 MODIFY( ADDRESS VARCHAR2(30) );

DESC MEMBER2;

 

--10) member_second 테이블 이름을 potential_member로 변경하여라.

RENAME MEMBER_SECOND TO POTENTIAL_MEMBER;

 

SELECT * FROM POTENTIAL_MEMBER;

 

TRUNCATE

TRUNCATE TABLE TABLE;

DROP

DROP TABLE TABLE;

--테스트용 테이블 생성

CREATE TABLE SCOTT.TEST_TBL1

AS SELECT * FROM SCOTT.STUDENT;

CREATE TABLE SCOTT.TEST_TBL2

AS SELECT * FROM SCOTT.STUDENT;

--테스트용 인덱스 생성

CREATE INDEX SCOTT.TEST_IND1

ON SCOTT.TEST_TBL1(STUDNO);

CREATE INDEX SCOTT.TEST_IND2

ON SCOTT.TEST_TBL2(STUDNO);

--테이블에 인덱스 존재여부 확인

SELECT INDEX_NAME, TABLE_NAME, STATUS,VISIBILITY

FROM DBA_INDEXES

WHERE TABLE_NAME LIKE 'TEST_%'

AND INDEX_NAME LIKE 'TEST_%';

--테이블 DROP

DROP TABLE SCOTT.TEST_TBL1;

SELECT * FROM SCOTT.TEST_TBL1;

** 차이점 DELETE : 디스크 상 공간은 그대로 가지고 있음 --> REORG 해야함

TURCATE : 용량은 줄고 구조는 살아있음

DROP : DROP TABLE을 하게되면 몽땅 삭제

--테이블 DROP 후 인덱스 재 확인 -> 테이블 TRUNCATE 시 해당 테이블의 인덱스도 같이 삭제됨

--인덱스 UNUSABLE ****INDEX TRUNCATEVALID로 다시바뀜

ALTER INDEX SCOTT.TEST_IND2 UNUSABLE;

TRUNCATE TABLE SCOTT.TEST_TBL2;

/

 

============== 차이 지웠을 때 구조적인 차이, 메모리 차이 HWM 하이워터마크=====================

--인덱스 UNUSABLE : 테이블 변경시 INDEX 반영이 안됨(그래서 리빌드가 필요함)

ALTER INDEX SCOTT.TEST_IND2 UNUSABLE;

TRUNCATE TABLE SCOTT.TEST_TBL2;

--인덱스 INVISIBLE ; 테이블 변경시 INDEX에 반영

ALTER INDEX SCOTT.TEST_IND2 INVISIBLE;

--인덱스 VISIBLE

ALTER INDEX SCOTT.TEST_IND2 VISIBLE;

--프로시저로 만든 TEST01 테이블에 인덱스 생성

CREATE INDEX SCOTT.TEST03_IND1 ON SCOTT.TEST03(NO);

--PLAN확인

SELECT NO

FROM SCOTT.TEST03

WHERE NO = 800; -- CTRL+E 실행계획

--인덱스 invisible 후 플랜 재 확인

ALTER INDEX SCOTT.TEST03_IND1 VISIBLE;

'Study Note > Database' 카테고리의 다른 글

DBMS_XPLAN.DISPLAY 다량데이터 조회시 참고사항  (0) 2016.02.16
SQL TUNING - 기본  (0) 2016.02.15
DML  (0) 2016.02.04
[Tool] Orange Character Set 설정하기  (0) 2016.02.04
SUB QUERY (서브쿼리)  (0) 2016.02.04

DML

 

DML: INSERT(입력) , UPDATE(변경) , DELETE (삭제) , MERGE(병합)

DDL : CREATE (생성) , ALTER(수정) , TRUNCATE(잘라내기), DROP(삭제)

TCL : COMMIT(확정) , ROLLBACK(취소)

SELECT : 어떤 분류에서는 DQL 라고 하기도 함

 

INSERT

INSERT 명령어는 테이블에 새로운 데이터를 입력할 때 사용

데이터를 입력할 때 숫자 값 이외에는 데이터를 ‘(홑따옴표)로 감싸야 함

 

 

문법

INSERT INTO table[(column1, column2,....)]

VALUES (value1 , value2 ....)

 

INSERT INTO DEPT2(DCODE,DNAME,PDEPT,AREA)

VALUES (9000, '특판1', '영업부', '임시지역');

COMMIT;

* 삽입 할 컬럼명 입력 해주고 컬럼 위치에 맞게 values 입력. (컬럼 없을 시 null 값 입력)

 

INSERT INTO DEPT2

VALUES (9000, '특판1', '영업부', '임시지역');

COMMIT;

* 컬럼 개수와 values의 개수가 맞아야함

 

※ ITAS 문

INSERT INTO PROFESSOR2

SELECT * FROM PROFESSOR

WHERE POSITION='정교수'; --  (중복삽입가능)

* PROFESSOR 테이블의 POSITION이 정교수인 데이터들만 PROFESSOR2테이블에 INSERT 해줌

 

 

INSERT INTO PROFESSOR2(NAME,ID,POSITION,PAY,HIREDATE)

SELECT NAME, ID, POSITION, PAY,HIREDATE FROM PROFESSOR

WHERE POSITION = '조교수';

 

INSERT ALL

여러 테이블에 여러 행 입력

 

INSERT ALL

INTO P_01(NO,NAME)

VALUES (1,'AAA')

INTO P_02(NO,NAME)

VALUES(2,'BBB')

SELECT * FROM DUAL;

COMMIT;

 

- -다른테이블의 데이터를 가져와서 입력하기

INSERT ALL

WHEN PROFNO BETWEEN 1000 AND 1999 THEN

INTO P_01 VALUES(PROFNO,NAME)

WHEN PROFNO BETWEEN 2000 AND 2999 THEN

INTO P_02 VALUES(PROFNO,NAME)

SELECT PROFNO,NAME

FROM PROFESSOR;

CREATE TABLE STUDENT3

AS SELECT * FROM STUDENT

WHERE 1=2;

** 데이터는 없고 구조만 가지고 싶다면 where 1=2(껍데기만 생성)

 

 

--STUDENT테이블의 1,2학년은 STUDENT3 테이블로 3,4학년은 STUDENT4 테이블로 넣으세요

 

INSERT ALL

WHEN GRADE BETWEEN 1 AND 2 THEN

INTO STUDENT3

WHEN GRADE BETWEEN 3 AND 4 THEN

INTO STUDENT4

SELECT * FROM STUDENT;

 

 

UPDATE

UPDATE 문장은 기존 데이터를 다른 데이터로 변경할 때 사용하는 방법

 

문법 

UPDATE TABLE

SET COLUMN = VALUE

WHERE 조건 ;

 

UPDATE PROFESSOR

SET BONUS = 100

WHERE POSITION = '조교수';

COMMIT;

 

 

--PROFESSOR 테이블에서 차범철 교수의 직급과 동일한 직급을 가진 교수들 중 현재 급여가 250만원이

-- 안 되는 교수들의 급여를 15% 인상하세요.

 

SELECT * FROM PROFESSOR

WHERE POSITION = (SELECT POSITION

FROM PROFESSOR

WHERE NAME ='차범철');

 

 

UPDATE PROFESSOR

SET PAY=PAY*1.15

WHERE POSITION = (SELECT POSITION

FROM PROFESSOR

WHERE NAME ='차범철')

AND PAY < 250;

 

**=> PAY가 1.15배 되서 update 된 것을 확인 할 수 있다.

 

 

--PROFESSOR 테이블에서 나한열 교수의 급여와 보너스를 주승재 교수와 동일하게 수정하여라

 

UPDATE PROFESSOR

SET (PAY,BONUS) = ( SELECT PAY,BONUS

FROM PROFESSOR

WHERE NAME = '주승재')

WHERE NAME = '나한열';

COMMIT;

 

--STUDENT 테이블에서 1학년 학생 중에 키가 175미만이고 몸무게가 60이상인 학생은 1학년의 평균 키와 평균

--몸무게로 수정하여라

 

UPDATE STUDENT

SET (WEIGHT,HEIGHT) = (SELECT AVG(WEIGHT),AVG(HEIGHT)

FROM STUDENT

WHERE GRADE = 1)

WHERE HEIGHT < 175 AND WEIGHT >= 60 AND GRADE = 1;

COMMIT;

 

DELETE

DELETE 문장은 데이터를 삭제하는 구문

DELETE는 바로 반환되지 않아 메모리에 남아있을 수 있음. (TRUNCATE는 바로 반환[ 복구불가능 ])

 

 구문

DELETE FROM TABLE

WHERE 조건

 

 

--DELETE 실습--

 

-- test table 생성

CREATE TABLE scott.test01 (no NUMBER, name VARCHAR2(20), addr VARCHAR2(20));

 

-- 프로시저를 통한 대용량 데이터 입력

BEGIN

FOR i IN 1..500000 LOOP

INSERT INTO scott.test01

VALUES(i, DBMS_RANDOM.STRING('A',19) ,

DBMS_RANDOM.STRING('Q',19) );

END LOOP;

COMMIT;

END;

 

select count(*) from scott.test01;

 

-- TEST01 테이블 사이즈 확인

select sum(bytes)/1024/1024 MB

from dba_segments

where owner = 'SCOTT'

and segment_name = 'TEST01'; --테이블명

 

-- 각 테이블 정보 확인

select table_name, num_rows, blocks, empty_blocks

from dba_tables

where owner='SCOTT'

and table_name='TEST01';

 

-- 통계 정보 생성

ANALYZE TABLE SCOTT.TEST01 COMPUTE STATISTICS;

 

생성후 위 각 테이블 정보 확인시

 

 

 

 

-- 실 사용 블럭 수 조회

SELECT COUNT(DISTINCT DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) ||

DBMS_ROWID.ROWID_RELATIVE_FNO(rowid)) "실사용 블록수"

FROM SCOTT.TEST01;

 

 

-- 테이블의 테이블스페이스 조회

SELECT TABLE_NAME, TABLESPACE_NAME

FROM DBA_TABLES

WHERE TABLE_NAME='TEST01';

 

 

-- 테이블 전체 삭제

DELETE FROM SCOTT.TEST01;

COMMIT;

--> DELETE로 삭제하게 되면 INSERTHWM이후에 있는 주소 값에 삽입하게 된다. --> reorg 작업

** reorg작업 : full scan 후 빈 공간에 차례대로 정렬하는 작업

 

REORG 작업

-- 테이블 스페이스 MOVE

ALTER TABLE SCOTT.TEST01 MOVE TABLESPACE EXAMPLE;

 

MERGE(위험성 때문에 잘 사용안함)

MERGE 란 여러 테이블 데이터를 합치는 병합을 의미

이 명령어는 문법이 다소 복잡하므로 잘 살펴봐야함

 

 문법

MERGE INTO Table1

USING Table2

ON (병합 조건절)

WHEN MATCHED THEN

UPDATE SET 업데이트 내용

DELETE WHERE 조건

WHEN NOT MATCHED THEN

INSERT VALUES(컬럼이름);

 

 

->다량 중복데이터 관리할 때 사용

--MERGE 작업 QUERY 1 (pt_01 테이블과 p_total 테이블 병합)

merge into p_total total

using pt_01 p01

on (total.판매번호 = p01.판매번호)

when matched then

update set total.제품번호=p01.제품번호

when not matched then

insert values(p01.판매번호,p01.제품번호,p01.수량,p01.금액);

 

merge into p_total total

using pt_02 p02

on (total.판매번호 = p02.판매번호)

when matched then

update set total.제품번호=p02.제품번호

when not matched then

insert values(p02.판매번호,p02.제품번호,p02.수량,p02.금액);

 

--확인

select * from p_total;

select * from pt_01;

select * from PT_02;

 

commit;

 

 

 

 

'Study Note > Database' 카테고리의 다른 글

SQL TUNING - 기본  (0) 2016.02.15
DDL  (0) 2016.02.04
[Tool] Orange Character Set 설정하기  (0) 2016.02.04
SUB QUERY (서브쿼리)  (0) 2016.02.04
JOIN  (0) 2016.02.04

+ Recent posts