DBMS2018. 7. 18. 11:06
반응형

8i, 9i, 10g, 11g 오라클 column 갯수의 제한은 1000개임.
티베로 5 1000개
티베로 6 1500개

https://docs.oracle.com/cd/B28359_01/server.111/b28320/limits003.htm#i288032

======================================
Logical Database Limits

Item Type of Limit Limit Value
GROUP BY clause Maximum length The GROUP BY expression and all of the nondistinct aggregate functions (for example, SUM, AVG) must fit within a single database block.
Indexes Maximum per table Unlimited
Indexes Total size of indexed column 75% of the database block size minus some overhead
Columns Per table 1000 columns maximum
Columns Per index (or clustered index) 32 columns maximum
Columns Per bitmapped index 30 columns maximum
Constraints Maximum per column Unlimited
Subqueries Maximum levels of subqueries in a SQL statement Unlimited in the FROM clause of the top-level query
255 subqueries in the WHERE clause
Partitions Maximum length of linear partitioning key 4 KB - overhead
Partitions Maximum number of columns in partition key 16 columns
Partitions Maximum number of partitions allowed per table or index 1024K - 1
Rows Maximum number per table Unlimited
Stored Packages Maximum size PL/SQL and Developer/2000 may have limits on the size of stored procedures they can call. The limits typically range from 2000 to 3000 lines of code.
See Also: Your PL/SQL or Developer/2000 documentation for details
Trigger Cascade Limit Maximum value Operating system-dependent, typically 32
Users and Roles Maximum 2,147,483,638
Tables Maximum per clustered table 32 tables
Tables Maximum per database Unlimited

반응형
Posted by [PineTree]
DBMS2010. 8. 9. 13:37
반응형

출처 : http://soff.tistory.com/106


이번 회에는 DB2 애플리케이션 개발 중에 오라클 DB 상이한 구문과 SQL 차이점에 대해서 설명하도록 하겠다. 출시될 DB2 Viper 2에서는 오라클 DB에서만 사용하는 outer join + 구문이나 connect by Recursive SQL, row number, 오라클 DB 전용 함수들이 DB2 레지스터리 변경 이후에 오라클 DB 동일하게 사용할 있어져서 오라클 DB 사용자들의 DB2 사용이 용이해 졌다.

 

Data Type

오라클 DB DB2 데이터 타입의 차이점은 DB2에서의 데이터 타입은 사용자 편의보다는 옵티마이저가 가장 해석할 있도록 세분화 되어 있다는 점이다. 이는 DB2 기본적으로 오라클 DB 달리 Rule base 옵티마이저 모드를 지원하지 않기에 옵티마이저가 최대한 해석할 있도록 만들어 주기 위함으로 보인다.

예를 들어 오라클 DB에서의 number 같이 정수, 소수를 대표하는 Data Type DB2에서는 크기에 따라 SMALLINT, INTEGER, BIGINT, DECIMAL(p,s)등으로 세분화 되어 쓰여지게 되어 있다.

 

Oracle Data Type

DB2 Data Type

Scope (DB2)

CHAR(n)

CHAR(n)

254 byte

VARCHAR2(n)

VARCHAR(n)

32,672 byte

LONG

LONG VARCHAR(n)

32,700 byte

NUMBER

SMLLINT

+ - 32,768 (5 digits, 2byte)

INTEGER

2 147 483 648 (10 digits, 4byte)

BIGINT

9,223,372,036,854,775,808 (64bit integers, 8type)

DECIMAL(p,s)

NUMERIC(p.s)

정밀도 31

REAL

 

DOUBLE (FLOAT)

+2.225E-307

BLOB

BLOB(n)

2GB

CLOB

CLOB(n)

2GB

NCLOB

DBCLOB

2GB

DATE

TIMESTAMP

0001-01-01-00.00.00.000000

DATE

0001-01-01

~ 9999-12-31

TIME

00:00:00

~ 24:00:00

DB2 오라클 DB에서와 같이 숫자와 문자간 자동 변환을 지원하지 않는다 따라서 문자와 숫자간 비교나 조인시 반드시 CAST, INT, CHAR 함수 등으로 변환을 해주어야 한다.

>

select * from tab1 where col1 = int(‘1’)

select * from tab1 where col1 = cast (‘1’ as int)

 

DB2에서의 날짜 연산

1.       to_char() 함수: DB2에도 오라클 DB to_char() 동일한 이름의 함수는 있으나 오라클 DB에서와 같이 날짜 형식의 다양한 포멧팅을 지원하지는 않는다. 오라클 DB TO_CAHR() 함수를 쓰기 위해서는 별도의 UDF 필요하다.(오라클/MS-SQL Built in Function 대한 DB2 UDF 첨부되어 있는 zip 파일을 참조해서 사용하기 바란다.)

2.       sysdate(oracle) => current date(현재 날짜), current timestamp (현재 시간소인)

3.       hex(current date) à 문자열 YYYYMMDD 형식 > 20080101

4.       date / year / month / day 함수 à 입력된 시간소인(혹은 날짜형식 문자열) 날짜(date yyyy-mm-dd), 년도(year –yyyy), (month – mm 2월인 경우 02 아니고 2 표시됨), (day – dd) 변환하는 scalar 함수

5.       날짜 더하기/ 빼기 “+/- n days”, “+/- months”, “+/- years” >current date + 1 months

6.       날짜끼리 경우 결과는 YYYYMMDD(decimal(8,0))형식으로 일자 사이의 기간을 나타내게 . ) values(date('2008-02-10') -date('2007-01-01')); à 00010109 (1 1개월 9)

7.       날짜 포멧 변경

char(current date, iso) – 2008-01-01

char(current date, eur) – 01.01.2008

char(current date, usa) – 01/01/2008

 

Page navigation 위한 Row Number

OLAP 함수인 row_number() over(order by 컬럼이름) 대체해서 사용해야 한다.

Select empno, fullname
From
(select empno
                  
, firstnme || ' ' || lastname as fullname
                  
, row_number() over (order by empno) as r_num
                             from
employee ) as t1
Where
r_num >= 10 and r_num <20

 

Dummy Table

Sysibm.sysdummy1 (DB2)

select * from sysibm.sysdummy1

Truncate Table

DB2에서는 오라클 DB에서의 Truncate table 존재하지 않는다. DB2에서 테이블의 데이터를 효율적으로 지우는 방법은 아래와 같다.

Import from /dev/null of del replace into 테이블이름

Alter table 테이블이름 activate not logged initially with empty table

à ALTER TABLE EMPLOYEE ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE;

 

Decode

Decode문은 지원하지 않는다. Case문으로 대체해야 한다.

 

UPDATE staff

SET comm = salary + DECODE(job,'Mgr',100,0)

 

UPDATE staff

SET comm = salary + CASE job

WHEN 'Mgr' THEN 100 ELSE 0 END

 

NULL 처리

Oracle

DB2

NVL(TO_CHAR(MGR_ID),'No Manager')

 

COALESCE(MGR _ID,'No Manager')

VALUE(MGR _ID,'No Manager')

 

Outer join

(+) 기호를 지원하지 않음으로, RIGHT OUTER JOIN / LEFT OUTER JOIN / FULL OUTER JOIN으로 대체해야 한다.


 

Sequence

데이터베이스 전체에서 관리되는 Sequence 별도로 테이블마다 제공되는 컬럼 sequence 존재한다. 사용법은 아래와 같다.

 

Oralce

DB2

시스템

시퀀스 정의

Create sequence test_seq start with 1

Increment by 1

Create sequence test_seq start with 1

Increment by 1

시퀀스 사용

Test_seq.nextval

Test_seq.currval

Nextval for test_seq

Prevval for test_seq

 

Procedure

1.       프로시저 생성시 CREATE OR REPLACE 옵션을 제공하지 않는다. 따라서 이미 존재하고 있는 프로시저일 경우 Drop 재생성 해야 한다. 이때 프로시저를 참조하는 Routine 있으면 같이 Drop하고 생성해 주어야 한다.

2.       데이터 타입 정의시 반드시 길이를 정해 주어야 한다. 길이가 정해져 있지 않은 데이터 타입은 사용이 불가능 하다. 또한 참조되는 객체의 길이가 서로 다를 경우 생성되지 않으므로 참조되는 객체의 길이와 타입은 반드시 동일하게 생성해 주어야 한다.

3.       /출력 값에 설정시 IN, OUT, INOUT 변수 앞에 선언하고 변수와 변수 타입(크기가 명시된) 선언한다.

4.       LANGUAGE SQL 옵션은 ver7.x에서는 반드시 써야 하지만 ver8.x부터는 선택 사항이다.

5.       Procedure 호출은 Call 명령어를 통해 호출한다.

à Call stored_procedure_name (input1, input2….)

 

CREATE OR REPLACE PROCEDURE test_sum_pr (i_log IN DATE, i_type IN VARCHAR2)

à CREATE PROCEDURE test_sum_pr (IN  i_log  DATE, IN i_type  VARCHAR(10))

 

Temporary Table

Temporary table 사용하기 위해서는 반드시 사용자 임시 테이블 스페이스 타입의 테이블 스페이스가 존재해야 하며, 세션에 독립적으로 생성되어 세션이 종료됨과 함께 자동으로 소멸된다.

 

-- User Temp 테이블 스페이스 작성

CREATE USER TEMPORARY TABLESPACE apptemps

MANAGED BY SYSTEM USING ('apptemps');

 

-- Temp Table 작성

DECLARE GLOBAL TEMPORARY TABLE t_employees LIKE employee NOT LOGGED;

 

Trigger

1.       트리거 생성시 CREATE OR REPLACE 옵션을 제공하지 않는다. 따라서 이미 존재하는 트리거일 경우 drop 생성해야 한다.

2.       Before 트리거에서 NO CASCADE 옵션은 필수 항목이다.

3.       MODE DB2SQL 옵션은 필수 항목이다.

4.       UPDATE & DELETE 구문은 Before&After 사용해야 한다.

5.       오라클 DB INSERT OR UPDATE OR DELETE ON 같은 다중 역할을 하는 트리거 생성이 불가능하다. 따라서 역할에 따라 트리거를 별도로 생성해 주어야 한다.

6.       INNER SQL(Select .. INTO) 통한 변수 설정이 불가능 하기 때문에 반드시 SET 통해 SELECT 결과를 변수에 입력하여야 한다. 이때 SELECT 문장의 값은 반드시 단일 Row여야 한다.

 

ID_EVENT (crud char(1), id varchar(40), name varchar(40))

ID_LOG (seq int, crud char(1), id varchar(40), name varchar(40), date date)

Oracle

CREATE OR REPLACE TRIGGER ID_EVENT_TR

AFTER INSERT OR UPDATE OR DELETE ON ID_EVENT

FOR EACH ROW

DECLARE

  ret binary_integer;

  crud char(1);

  vid varchar2(40);

  vname varchar2(40);

BEGIN

  if inserting then

    crud := 'C';    vid := :new.ID;    vname := :new.NAME;

  elsif deleting then

    crud := 'D';    vid := :old.ID;    vname := :old.NAME;

  else

    crud := 'U';     vid := :old.ID;     vname := :old.NAME;

  end if;

insert into ID_LOG (seq, crud, id, name, date)

values (test.nextval, crud, vid, vname ,sysdate);

END;

DB2

CREATE TRIGGER ID_EVENT_TR_DEL1
  AFTER  DELETE  ON
ID_EVENT
 
REFERENCING  OLD AS OLD
  FOR EACH ROW
  MODE DB2SQL
  BEGIN ATOMIC
    DECLARE
ret DECIMAL(31,0);

    DECLARE
crud CHAR(1);
    DECLARE
vid VARCHAR(40);
    DECLARE
vname VARCHAR(40);
    SET
crud = 'D';
    SET
vid = OLD.ID;
    SET
vname = OLD.DOC_ID;
   insert into
ID_LOG (seq, crud, id, name, date)
      VALUES
(nextval FOR test, crud, vid, vname ,current date);
  END
;

CREATE TRIGGER
ID_EVENT_TR_INS1
  AFTER   INSERT  ON
ID_EVENT
 
REFERENCING   NEW AS NEW
  FOR EACH ROW
  MODE DB2SQL
  BEGIN ATOMIC
    DECLARE
ret DECIMAL(31,0);

    DECLARE
crud CHAR(1);
    DECLARE
vid VARCHAR(40);
    DECLARE
vname VARCHAR(40);
    SET
crud = 'C';
    SET
vid = NEW.ID ;
    SET
vname = NEW.NAME;
   insert into
ID_LOG (seq, crud, id, name, date)
      VALUES
(nextval FOR test, crud, vid, vname ,current date);
  END
;

CREATE TRIGGER
ID_EVENT_TR_UPD1
  AFTER  UPDATE  ON
ID_EVENT
 
REFERENCING    OLD AS OLD     NEW AS NEW
  FOR EACH ROW
  MODE DB2SQL
  BEGIN ATOMIC
    DECLARE
ret DECIMAL(31,0);

    DECLARE
crud CHAR(1);
    DECLARE
vid VARCHAR(40);
    DECLARE
vname VARCHAR(40);
    SET
crud = 'U';
    SET
vid = OLD.ID ;
    SET
vname = OLD.NAME;
   insert into
ID_LOG (seq, crud, id, name, date)
      VALUES
(nextval FOR test, crud, vid, vname ,current date);
  END
;

 

Function

Built-in 함수를 제외하고 유저에 의해 생성된 Function UDF(User Define Function) 한다.

1.       Input parameter 선택 사항이지만 가로는 필수 사항이다.

2.       Return Type 아래 3가지 하나는 반드시 명시되어야 한다.

A.      Scalar: 단일 반환

B.      Table: From절에 사용되는 Table 반환

C.      Row: Transform 함수로 사용되면 하나의 row 반환

3.       LANGUAGE SQL V8부터 옵션 사항이다.

4.       Return 키워드 후에는 반드시 SQL 함수 Body 작성해야 한다.

 

예제)

DB2 LAST_DAY 함수

CREATE FUNCTION DB2DEV.LAST_DAY (D DATE)

  RETURNS DATE

  SPECIFIC DB2APP.LAST_DAYDATE

  LANGUAGE SQL

RETURN D + 1 month - day(D + 1 month) day;

 

오라클 DB LAST_DAY 함수

CREATE FUNCTION months_between(d1 TIMESTAMP, d2 TIMESTAMP)

    RETURNS FLOAT

    LANGUAGE SQL

RETURN 12*(year(d1) - year(d2)) + month(d1) - month(d2)

+ (TIMESTAMPDIFF(2,CHAR(d1 - (d2 + (12*(year(d1) - year(d2))        

+ month(d1) - month(d2)) MONTHS))) / 2678400.0)

 

SQL PL (Oracle PL/SQL)

변수 정의와 규칙

Oracle PL/SQL 같은 경우 아래의 4가지 위치에 변수 정의가 가능하다.

1.       스토어드 프로시저 또는 함수 파라미터 리스트

2.       스토어드 프로시저, 함수, 트리거의 내부

3.       패키지 정의

4.       패키지 body 정의

 

DB2에서는 오라클 DB에서와 같이 함수나 프로시저를 그룹화하는 패키지 개념이 없다. 따라서 변수 정의는 패키지를 제외한 위의 가지 경우만 허용된다.

DB2 SQL PL에서도 native data type user defined distinct type 여러 형태 정의가 가능하다. 변수 정의시 반드시 DECLARE 구문을 써서 정의하여야 하며, 변수 정의를 위해서는 반드시 BEGIN … END 블록 안에서 정의되어야 한다. 초기값 설정 이후 변수에 값을 설정할 경우 DB2에서는 SET 문장을 써서 변수를 assign 한다.

 

> 초기값 설정

Oracle PL/SQL: l_value NUMBER(10,2) :=0.0;

DB2 SQL PL:  DECLARE l_value NUMERIC(10,2) DEFAULT 0.0;

 

> 변수 할당

Oracle PL/SQL: l_value = 99.99;

DB2 SQL PL: SET l_value = 99.99;

à Trigger 경우 INNER SQL(Select .. INTO) 통한 변수 설정이 불가능 하기 때문에 반드시 SET 통해 SELECT 결과를 변수에 입력하여야 한다. 이때 SELECT 문장의 값은 반드시 단일 Row여야 한다.

SET l_value =(SELECT balance from account_info where account_no = actNo);

 

Cursor 처리

1.       응용프로그램에서 결과 집합을 검색하기 위해 사용하는 기법으로 Select 문에서 여러 건의 데이터를 반환하는 경우에 사용된다.

2.       커서는 declare / open / fetch / close 단계로 사용된다.

3.       Open 커서는 UOW(unit of work) 종료시(commit / rollback) 소멸되지만 DB2에서는 With HOLD 옵션으로 커서의 위치를 유지할 있다.

4.       DB2 Memory level Lock 사용하며 그에 따른 Cursor 유형도 읽기 전용(READ ONLY) 업데이트 가능한 UPDATEABLE 커서가 있다.

5.       UPDATEABLE(FOR UPDATE OF) 사용하면 데이터를 Fetch 하는 동안 S모드 대신 U모드 LOCK 적용되어 Deadlock 방지할 있다.

 

Oracle

DB2

용도

CURSOR cursor_name

[(cursor_parameter(s))]

IS select_statement;

DECLARE cursor_name

CURSOR [WITH HOLD] [WITH RETURN] [TO CALLER | TO CLIENT] FOR select-statement

[FOR READ ONLY|UPDATE OF|]

Declare

OPEN cursor_name

[(cursor_parameter(s))];

OPEN cursor_name [USING

host-variable]

Open

FETCH cursor_name INTO

variable(s)

FETCH [from] cursor_name

INTO variable(s)

Fetch

UPDATE table_name

SET statement(s)...

WHERE CURRENT OF

cursor_name;

UPDATE table_name

SET statement(s)...

WHERE CURRENT OF

cursor_name

Update Fetch

DELETE FROM table_name

WHERE CURRENT OF

cursor_name;

DELETE FROM table_name

WHERE CURRENT OF

cursor_name

Delete Fetch

CLOSE cursor_name;

CLOSE cursor_name

Close

 

커서 예외 처리

Oracle

DB2

%ISOPEN

Open cursor에서 커서가 이미 열려 있는 상태면 SQLCODE = -501 / SQLSTATE=24501

Fetch에서 커서가 아직 열려 있지 않은 상태면 SQLCODE = -502 / SQLSTATE=24502

Oracle

IF c1%ISOPEN THEN

        fetch c1 into var1;

ELSE    -- cursor is closed, so open it

      OPEN c1;

      fetch c1 into var1;

END IF;

DB2

DECLARE cursor_notopen CONDITION FOR SQLSTATE 24501;

DECLARE CONTINUE HANDLER FOR cursor_notopen

   BEGIN

         open c1;

         FETCH c1 int var1;

   END;

     ...

   FETCH c1 into var1;

%NOTFOUND

SQLCODE = 100이거나 SQLSTATE = ‘02000’

Oracle

OPEN cur1;

LOOP

   FETCH cur1 INTO v_var1;

   EXIT WHEN cur1%NOTFOUND;

      ...

   END LOOP;

DB2

DECLARE SQLCODE int DEFAULT 0;

   ……

   OPEN c1;

   L1: LOOP

         FETCH c1 INTO v_var1;

         IF SQLCODE = 100 THEN

                 LEAVE L1;

         END IF;

         ...

   END LOOP L1;

%FOUND

SQLCODE = 0이거나 SQLSTATE = ‘00000’

Oracle

DELETE FROM emp  WHERE empno = my_empno;

   IF SQL%FOUND THEN    -- 행이 삭제 되었을 경우

      INSERT INTO emp_table

VALUES (my_empno, my_ename);

DB2

DELETE FROM emp WHERE empno = my_empno;

IF SQLCODE = 0  THEN    -- delete succeeded

   INSERT INTO emp_table VALUES (my_empno, my_ename);

%ROWCOUNT

Fetch First n rows only 사용하거나 Loop 사용하여 count 증가

exit/GET DIAGNOSTICS 문을 사용하여 반환된 계산

Oracle

LOOP

     FETCH c1 INTO my_ename,my_deptno;

     IF c1%ROWCOUNT > 10 THEN

        EXIT;

    END IF;

      ...

END LOOP;

 

DELETE FROM emp_table

WHERE ...

IF SQL%ROWCOUNT > 10 THEN     

-- 10 이상 삭제

      ...

   END IF;

DB2

DECLARE rc INT DEFAULT 0;

   …….

   DELETE FROM emp_table WHERE ...

   GET DIAGNOSTICS rc = ROW_COUNT;

   IF rc > 10 THEN      ...

   END IF;

GET DIAGNOSTICS SELECT /SELECT INTO 문장은 지원하지 않는다.

개의 ROW SELECTING 되지 않을 경우 SQLCODE = 100

하나의 ROW SELECTING 경우 SQLCODE=0

하나의 ROW 이상이 SELECTING 경우 SQLCODE=-811 (SQLSTATE=21000 – SQLERROR)

       

 

Debugging

DB2에는 오라클 DB dbms.output.put_line 같은 함수가 존재 하지 않는다. 따라서 dbms.output.put_line 함수와 같은 UDF Fuction 만들거나, 디버깅 테이블을 만들어 디버깅 하고자 하는 값을 새로 만든 디버깅 테이블에 Insert 하는 방법이 있다.

아래의 방법은 put_line UDF 생성하여 디버깅 하는 방법에 대한 설명이다. 해당 원문은 아래의 Site에서 확인 하기 바란다.

http://www.ibm.com/developerworks/db2/library/techarticle/0302izuha/0302izuha.html

 

put_line UDF생성 방법

CREATE PROCEDURE TESTCASE() RESULT SETS 0 LANGUAGE SQL

L_TESTCASE:

BEGIN NOT ATOMIC 

                  DECLARE V_DEPTNO               SMALLINT;

                  DECLARE V_DEPTNAME           VARCHAR(20);

                  DECLARE V_DIVISION               VARCHAR(20);

-- FOR DEBUG

                  DECLARE V_NUM     SMALLINT DEFAULT 0;

                  DECLARE V_MSG1   VARCHAR(4000);

                  DECLARE V_MSG2   VARCHAR(1);

-- END

-- SAMPLE1

                  SET V_NUM=2000;

                  SET V_MSG1='debugging start';

                  VALUES(PUT_LINE(V_NUM,V_MSG1)) INTO V_MSG2;

-- SAMPLE2

                  VALUES(PUT_LINE(SMALLINT(2),'this is no2')) 

                    INTO V_MSG2;

-- SAMPLE3

                  VALUES(PUT_LINE(3)) INTO V_MSG2;

-- SAMPLE4

                  VALUES(PUT_LINE('##number4##')) INTO V_MSG2;

-- SAMPLE5

                  SET V_NUM = 0;

   FOR V_C1_REC AS C1 CURSOR FOR

                  SELECT DEPTNUMB, DEPTNAME, DIVISION

                  FROM ORG ORDER BY DEPTNUMB DESC

   DO

              SET V_DEPTNO   = v_C1_REC.DEPTNUMB;

                  SET V_DEPTNAME = v_C1_REC.DEPTNAME;

                 SET V_DIVISION = v_C1_REC.DIVISION;

                  SET V_NUM = V_NUM + 1;

                  SET V_MSG1 ='DEPTNO=' || CHAR(V_DEPTNO)||',' ||'DEPTNAME='||V_DEPTNAME||','

                                   ||'DIVISION='||V_DIVISION;

                  VALUES(PUT_LINE(V_NUM,V_MSG1)) INTO V_MSG2;

   END FOR;

                  VALUES(PUT_LINE(32000,'end of the program')) 

                    INTO V_MSG2;

END          L_TESTCASE

 

<참조>

§   Oracle to DB2 UDB Conversion Guide(IBM.com/redbooks)

§   DB2 사용자 가이드(IBM)


반응형
Posted by [PineTree]
DBMS2009. 10. 7. 15:55
반응형

 

오라클 자료형과 MSSQL 자료형 변환시 참고하세요.

 

Oracle data type SQL Server data type Alternatives

BFILE

VARBINARY(MAX)

Yes

BLOB

VARBINARY(MAX)

Yes

CHAR([1-2000])

CHAR([1-2000])

Yes

CLOB

VARCHAR(MAX)

Yes

DATE

DATETIME

Yes

FLOAT

FLOAT

No

FLOAT([1-53])

FLOAT([1-53])

No

FLOAT([54-126])

FLOAT

No

INT

NUMERIC(38)

Yes

INTERVAL

DATETIME

Yes

LONG

VARCHAR(MAX)

Yes

LONG RAW

IMAGE

Yes

NCHAR([1-1000])

NCHAR([1-1000])

No

NCLOB

NVARCHAR(MAX)

Yes

NUMBER

FLOAT

Yes

NUMBER([1-38])

NUMERIC([1-38])

No

NUMBER([0-38],[1-38])

NUMERIC([0-38],[1-38])

Yes

NVARCHAR2([1-2000])

NVARCHAR([1-2000])

No

RAW([1-2000])

VARBINARY([1-2000])

No

REAL

FLOAT

No

ROWID

CHAR(18)

No

TIMESTAMP

DATETIME

Yes

UROWID

CHAR(18)

No

VARCHAR2([1-4000])

VARCHAR([1-4000])

Yes

반응형
Posted by [PineTree]
DBMS2009. 8. 24. 09:26
반응형
오라클은 올 4월 오라클 데이터베이스 10g의 TPC-C 결과를 발표하며 32개 프로세스 부분에서 1분에 160만 트랜잭션을 처리해 세계 신기록을 기록했다고 밝힌 바 있다. 이러한 수치가 우리에게 의미하는 바는 무엇이며 오라클 10g가 다른 DBMS 제품과 차별화되는 점은 무엇인지 성능 측면에서 살펴본다.

많은 DBMS 업체들이 자사 제품 성능의 우수함을 주장하기 위해 공신력 있는 기관의 벤치마크 결과를 인용한다. 이때 많이 근거로 제시되는 것이 바로 가장 객관적이라고 알려진 TPC (Transaction Processing Performance Council)이다. TPC는 TPC-C와 TPC-D라는 기준을 가지고 지속적으로 벤치마크 결과를 발표하는데, 전자는 TPC에 의해 기획된 OLTP(OnLine Transaction Processing, 실시간 데이터 처리) 벤치마크 테스트로 여기서 세계 신기록을 수립했다는 것은 32-프로세스 등 해당 부분에서 가장 좋은 성능을 가진 DBMS임을 의미한다. 마치 수영이나 육상 등의 시합에서 100m를 얼마만에 주파했는지 시간 기록이 있듯이 TPC-C도 처리 속도에 분당(tpmC) 혹은 비용($/tpmC) 대비 DBMS의 기록인 셈이다.

<표 1>은 각 데이터 볼륨 사이즈별 TPC-H의 결과치와 시간당 처리 쿼리(QphH) 순으로 상위 3위를 정리한 것이다. TPC-H는 의사결정 벤치마크 결과로, 복잡한 질의를 실행하고 중대한 비즈니스 질문에 대한 답변을 주는 의사결정 지원 시스템을 선택하는 기준으로 활용되곤 한다. <표 1>에서 볼 수 있듯이 100GB에서 QphH의 수치는 MS SQL 서버 2005가 가장 뛰어난 성능을 보인다. 그러나 300GB 이상의 데이터 볼륨의 경우 오라클 데이터베이스 10g의 성능이 가장 뛰어난 처리능력을 보여주는 것을 알 수 있다. 즉 오라클은 중대형으로 올라가면 올라갈수록 진가를 발휘하는 셈이다. 실제로 시장에서는 MS SQL은 중소형 DBMS, 오라클은 대형 DBMS라는 인식이 형성돼 있다.

그렇다면 왜 오라클은 중대형 서버에서 제 성능을 발휘하는 것일까. 지금부터 실제 주요 DBMS와 오라클을 직접 비교해보자. 기능 비교는 DBMS의 성능을 결정하는 핵심 요인을 중심으로 이루어지며 구체적으로는 동시성 모델과 인덱싱, 파티셔닝, 병렬 실행, 클러스터링 등을 살펴볼 예정이다.

① 동시성 모델 : 데이터베이스의 Locking 메커니즘을 비교하기 위한 것으로, 얼마나 많은 사용자가 동시에 같은 데이터 읽기 일관성을 유지하는가가 관건이다.

② 파티셔닝 : 대량의 데이터를 처리하는데 있어서 파티셔닝, 즉 특정 값을 기준으로 데이터를 분할하는 방법

③ 병렬 실행 : 멀티 CPU 환경에서 CPU 별로 균등하게 작업을 분배해 전체 처리 성능을 높인다.

④ 클러스터링 : 복수의 노드를 단일 노드처럼 처리하여 성능과 고가용성을 높이는 요인이 된다.





오라클 데이터베이스 10g vs. SQL 서버 2005
먼저 오라클의 가장 최신 버전인 오라클 데이터베이스 10g 릴리즈 2와 마이크로소프트(이하 MS)의 SQL 서버 최신 제품인 SQL 서버 2005의 기술적인 차이점을 성능과 확장성 관점에서 비교해보자.

동시성 모델
동시성 모델(Concurrency Model)은 멀티-유저 환경에서 특정 사용자에 의해 수행된 데이터 업데이트가 다른 사용자에게 영향을 미치는지 여부를 알 수 있는 매우 중요한 지표다. 오라클 데이터베이스 10g와 SQL 서버 2005는 동시성 모델의 구현 방법에서 차이를 보이는데 주요 차이점은 <표 2>와 같다.
<표 1> 볼륨 사이즈별 TPC 상위 3위
100GB 결과
기업 시스템 vQphH 가격/
QphH
System
Availability
데이터베이스 운영체제 Date
Submitted
클러
스터
hp Hp ProLiant DL585 G1 4P 12,600 9.43$ 11/07/05 MS SQL 서버 2005
엔터프라이즈X64 에디션
MS 윈도우
서버 2003
엔터프라이즈
64 에디션
11/04/05 N
IBM IBM e서버 325 12,216 70.68$ 11/08/03 IBM DB2 UDB 8.1 수세 리눅스
엔터프라이즈
서버 8
07/29/03 Y
SunFire V890 10,487 46.29$ 08/15/05 썬 사이베이스
IQ 12.6 싱글
썬 솔라리스 10    

300GB 결과
기업 시스템 vQphH 가격/
QphH
System
Availability
데이터베이스 운영체제 Date
Submitted
클러
스터
hp HP BladeSystem ProLiant BL25p Cluster 8P DC 18,725 27.97$ 11/11/05 오라클 10g
엔터프라이즈
에디션 R2 w/ Partioning
레드햇
엔터프라이즈
리눅스4 ES
11/11/05 Y
hp HP BladeSystem ProLiant BL25p Cluster 8P 13,284 34.20$ 10/31/05 오라클 데이터베이스 10g릴리즈 2 엔터프라이즈 에디션 레드햇 엔터프라이즈 리눅스 4 ES 09/16/05 Y
IBM IBM e서버 325 13,194 65.44$ 11/08/03 IBM DB2 UDB 8.1 수세 리눅스 07/29/03 엔터프라이즈 서버 8 07/29/03 Y

1000GB 결과
기업 시스템 vQphH 가격/
QphH
System
Availability
데이터베이스 운영체제 Date
Submitted
클러
스터
hp HP Intergrity
Superdome
엔터프라이즈 서버
68,100 59.00$ 01/18/06 오라클 데이터베이스 10g R2 엔터프라이즈 에디션 w/Partitioning HP UX 11.i V2 64비트 08/08/05 N
IBM IBM 2서버
xSeries 346
53,451 32.80$ 02/14/05 IBM DB2 UDB 8.2 수세 리눅스 엔터프라이즈 서버 9 02/14/05 Y
hp HP ProLiant Dl585 Cluster 48P 35,141 59.93$ 10/21/04 오라클 10g RAC/ with Partitioning 레드햇 엔터프라이즈 Linux AS 3 10/22/04 Y

10000GB 결과
기업 시스템 vQphH 가격/
QphH
System
Availability
데이터베이스 운영체제 Date
Submitted
클러
스터
Sun fire E25K
server
108,099 53.80$ 01/23/06 오라클 10g 엔터프라이즈 에디션 R2 w/Partitioning 썬 솔라리스 10 11/29/05 N
IBM IBM e서버
p5 575
104,100 61.17$ 08/15/05 IBM DB2 UDB 8.2 IBM AIX 5L
V5.3
05/20/05 Y
hp HP Integrity
Superdome
엔터프라이즈 서버
86,282 161.24$ 04/06/05 오라클 데이터베이스 10g 엔터프라이즈 에디션 HP UX 11.i
V264비트
10/07/04 Y

오라클 데이터베이스에서 구현되는 멀티-버전 읽기 일관성(multi-version read consistency)은 예를 들면, 트랜잭션에 의해 업데이트가 발생한 경우 기존 데이터 값은 데이터베이스의 언두(undo) 레코드에 기록이 되기 때문에 트랜잭션이 커밋되기 전까지 언두 레코드에 저장된 이전 버전의 정보를 사용자에게 반환하고 따라서 데이터의 읽기 일관성을 보장한다.

반면 SQL 서버 2005가 기본적으로 제공하는 격리(isolation) 모델은 읽기 작업에 대해 공유 읽기 잠금(shared read lock)을 사용한다. 즉 공유 잠금이 적용된 경우 현재 읽기 작업이 수행되고 있는 데이터에 대한 업데이트가 불가능하다. 이러한 모델은 읽기/쓰기 작업이 동시에 발생하는 환경에서 동시 요청을 처리하는데 성능상 불리할 수밖에 없다. 또한 애플리케이션이 점유하는 잠금의 수가 점차 증가함에 따라 잠금 에스컬레이션(lock escalation, 잠금의 확대, 예를 들어 row 레벨 락에서 테이블 락으로 확대되는 현상)이 발생해 동시성이 한층 더 제약되고 데드락(두 세션이 각각 상대방에 대해서 lock을 잡고 있는 상태)으로 연결될 가능성도 있다. 이러한 문제 때문에 MS SQL 서버 2005에서는 이러한 문제에 대응하기 위해 구문 레벨 읽기 일관성(read committed with snapshots), 트랜젝션 레벨 읽기 일관성(snapshot isolation) 등 두 가지 격리 수준을 추가했다.
<표 2> 오라클 10g와 MS SQL 서버 2005의 동시성 모델 비교

오라클 데이터베이스 10g SQL 서버 2005
멀티 버전 읽기 일관성
(Multi-version read Consistency)
향상 가능 디폴트 아님.
기능의 사용을 위해 활성화해야 함
로우 레벨 잠금의 에스커레이션 잠금
(Non-escalating row-level locking)
지원 지원 안됨
(Locks escalate)

<표 3> 인덱스 유형 비교
인덱스 유형 오라클 데이터베이스 10g SQL 서버 2005
B-트리 인덱스 지원 지원
B-트리 클러스터 인덱스 지원 지원하지 않음
해시 클러스터 인덱스 지원 지원하지 않음
리버스 키 인덱스 지원 지원하지 않음
비트맵 인덱스 지원 지원하지 않음
비트맵 조인 인덱스 지원 지원하지 않음
기능 기반 인덱스 지원 지원하지 않음. 계산된 컬럼(computed Column)에 대해 서도 인덱스를 생성할 수 있지만 해당 컬럼이 테이블 내에 실제로 존재하고 있어야 함.
도메인 인덱스 지원 지원하지 않음
IOT 지원 지원(clustered index)

<그림 1> 비트맵 조인 인덱스

이 두 가지 격리 수준은 각각 오라클에서 예전부터 지원해 온 READ COMMITTED와 SERIALIZABLE 격리 수준에 대응된다. 이 두 가지 격리 수준에서는 특정 읽기 작업이 동일한 데이터에 접근하는 다른 읽기/쓰기 작업을 블로킹하지 않으며 쓰기 작업 역시 읽기 작업을 블로킹하지 않는 것이 특징이다. 먼저 트랜젝션 레벨 읽기 일관성은 로우 버저닝(row versioning)을 기반으로 하고 있다. 이는 커밋된 데이터 로우를 포함하고 있는 여러 버전들의 링크드 체인(linked chain), 즉 원래의 데이터 위치를 추적함으로써 읽기 일관성을 보장하는 방법이다. 링크드 체인은 tempdb라는 임시 스토어드 프로시저(temp stored procedure)와 기타 임시 작업을 위한 데이터베이스 저장공간에 위치한 별도의 버전 저장소(version store)에 저장된다.

이러한 SQL 서버 2005의 트랜젝션 레벨 읽기 일관성은 혁신적인 기술로 보기 힘들다. SQL 서버 2000에서는 지원되지 않았기 때문에 이전 버전보다 개선된 것은 사실이나 오라클은 이미 오래 전부터 멀티-버전 읽기 일관성을 기본으로 지원해왔기 때문이다. 이 외에도 SQL 서버 2005는 동시성 모델에 있어서 다음과 같은 한계들을 갖는다.

① 관리자는 데이터베이스 레벨에서 명시적으로 설정한 경우에만 read-com mitted with snapshot 또는 snaption isolation이 활성화된다(기본적으로는 성능상의 이유 때문에 ‘disable’되어 있다).

② 기존에 운영 중이던 SQL 서버 애플리케이션의 경우 이 모드를 구현하려면 SQL 서버 애플리케이션을 오라클 환경으로 이전하는 것과 동등한 수준의 수정 작업이 요구된다. 왜냐하면 SQL 서버 2000에서는 이러한 기능이 지원되지 않았기 때문이다. 읽기 잠금을 이용하는 애플리케이션에 멀티-버전 읽기 일관성을 적용하기 위해서는 일정 수준의 재설계와 재개발 작업이 불가피하다.




인덱싱
인덱스가 데이터에 대한 신속한 접근을 제공하기 위해 생성되는 중요한 기능 중에 하나라는 것은 데이터베이스를 사용하는 사람들에게는 상식적인 이야기다. 인덱스를 이용하면 디스크 I/O 작업을 크게 줄이고 데이터 인출 성능을 개선할 수 있으며 성능 향상을 기대할 수 있다. 그렇다면 오라클 데이터베이스 10g와 MS SQL 서버 2005의 인덱싱은 어떠한 차이가 있을까. <표 3>은 두 제품이 지원하는 인덱싱 메커니즘의 차이를 요약한 것이다.

오라클과 SQL 서버 2005는 모두 고전적인 B-트리 인덱스 구조를 지원한다. B-트리 인덱스는 순차적으로 정렬된 키 값을, 실제 값이 저장된 테이블 로우의 저장 위치와 연계한 형태로 구성된다. B-트리 인덱스는 별도의 인덱스 영역에 키 값을 기준으로 정렬되어 있고 이 인덱스 영역은 실제 데이터의 위치 정보(RowID)를 가지고 있다. 또한 두 제품 모두 IOT(Index-Organized Table)을 지원한다(MS는 clustered index라는 용어를 사용한다). IOT는 테이블 로우를 프라이머리 키 인덱스의 리프 노드에 저장하고 있기 때문에 프라이머리 키를 기준으로 한 조건 및 영역 검색에서 뛰어난 성능을 보여준다. IOT의 대표적인 성격은 모든 테이블의 데이터를 인덱스처럼 저장하는 것이다. 즉 인덱스 입력 항목의 두 번째 요소로 행의 RowID를 가지지 않고 실제 데이터 행이 B-트리 인덱스에 저장된다.

게다가 오라클은 스태틱 비트맵 인덱스(static bitmap index)와 비트맵 조인 인덱스(bitmap join index)를 추가로 지원한다. 이 두 가지 인덱스는 데이터 웨어하우징 환경의 로드/쿼리 작업에서 좋은 성능 효과를 보여준다. 비트맵 인덱스는 RowID와 값에 대해 BIT 값으로 저장을 함으로써 나이, 성별, 지역처럼 전체 레코드 건수에 비해 카디널리티(선택도)가 낮은 속성들과 OR, AND 연산시에 효과적으로 사용할 수 있는 인덱스 구조이다. 또한 오라클 9i부터 지원되는 비트맵 조인 인덱스는 두 개 이상의 테이블에 조인 인덱스를 생성함으로써 질의 처리를 위한 조인에서 오는 부하를 피하고 그만큼 성능 향상을 가져올 수 있다.

비트맵 인덱스는 테이블 로우의 저장 위치 목록 대신 각 키 값에 대한 비트맵(또는 비트 벡터)을 사용한다. 비트맵의 각 비트는 테이블의 로우에 대응한다. 테이블의 로우가 키 값을 포함하고 있는 경우에 해당 비트가 설정된다. 로우의 저장 위치를 저장하는 방식과 비교했을 때 비트맵 표현 방식은 매우 많은 비용 절감 효과를 제공한다. B-트리 인덱스는 실제로 조건이 비교되는 컬럼 값에 대한 테이블의 원시 값과 Row의 물리적인 주소인 RowID를 인덱스 블럭에도 저장하므로 데이터의 중복 저장에 따른 공간낭비가 발생한다. 반면 비트맵 인덱스는 저장공간에 인덱스 컬럼 값이 아닌 1과 0의 비트값이 저장되고, 스캔에 의한 데이터 추출이 아닌 비트 연산에 의한 데이터 추출을 하기 때문에 성능을 높일 수 있다. 특히 선택도(cardinality)가 낮은 데이터가 사용되는 경우 효과적이다.

비트맵 인덱스는 AND, OR 등 고속의 불리언(Boolean) 연산을 통해 서로 다른 인덱스의 비트맵을 조합하는 형태로도 활용된다. 여러 개의 조건에 대한 연산을 수행하기 위해 각 조건에 대응되는 인덱스들을 WHERE절 내에서 효과적으로 조합한다. WHERE절 내의 모든 조건을 만족하지 않는 로우는 테이블에 대한 액세스가 수행되기 전에 필터링되며 상황에 따라 극적인 성능 개선도 기대할 수 있다.

오라클 데이터베이스에서는 IOT에 대한 비트맵 인덱스를 생성하고, IOT를 데이터 웨어하우징 환경을 위한 팩트 테이블(fact table, 다차원 모델에서 중심이 되는 테이블)로 활용하는 것이 가능하다. 비트맵 조인 인덱스는 두 개 이상의 테이블을 조인(join)하기 위해 사용되는 비트맵 인덱스이다. 이를 이용하면 실제 테이블을 조인할 필요가 없으며 제약 조건을 미리 실행함으로써 실제로 조인되는 데이터의 양을 크게 줄일 수 있다. 또한 비트 단위 연산을 통해 Bit map join index를 이용하는 쿼리의 실행 속도도 개선할 수 있다.

<그림 1>은 비트맵 조인 인덱스의 대표적인 사례다. 조건절을 통해 Customer 테이블과 Sales 테이블 사이의 조인을 미리 계산하는(precomputation) 역할을 하게 되므로 두 개의 테이블 질의 시 비트맵 조인 인덱스를 통하게 되면 하나의 테이블에만 접근하면 된다. 게다가 비트맵 조인 인덱스는 다수의 디멘션 테이블을 포함하고 있으므로 비트 단위 연산이 필요치 않다(실제로 단일 테이블에 비트맵 인덱스의 형태로 스타 스키마를 적용한 경우에는 비트 단위 연산이 반드시 필요하다). 다양한 형태의 스타 스키마(Star Schema, 데이터 웨어하우징에서 복잡한 정보를 모델링하는 표준형 기술로, 중심이 되는 Fact 테이블을 중심으로 디멘전(dimension) 테이블이 붙어있는 형태이다)에 대한 쿼리 테스트를 수행해 보면 비트맵 조인 인덱스를 사용한 쿼리가 실제 성능 개선 효과를 제공한다는 사실을 확인할 수 있다.

파티셔닝
파티셔닝(Partitioning)은 테이블, 인덱스 등 대규모 데이터베이스 구조를 더 작고 관리하기 쉬운 단위로 분해하는 기능이다. 주로 관리성과 가용성을 개선하기 위해 활용되지만 성능 측면에서도 몇 가지 혜택을 제공한다.
<그림 2> 스타 스키마 모델

파티셔닝은 애플리케이션 시나리오 별로 다양한 파티셔닝 테크닉을 고려할 수 있다. 예를 들어 레인지 파티셔닝(Range Partition ing)은 일정 영역의 컬럼 값을 이용해 로우를 파티션에 맵핑한다. 이 옵션은 히스토리(history) 데이터베이스 즉 이력 데이터에 특히 유용하게 활용되며 데이터 웨어하우스 환경의 롤링 윈도우(rolling window, 주기적으로 새로운 데이터가 추가되면서 오래된 데이터는 데이터 웨어하우스에서 삭제되는 것) 지원을 위한 이상적인 파티셔닝 방법으로 이용되기도 한다.

해시 파티셔닝(Hash Partitioning)은 파티션된 컬럼에 해시 함수를 적용해서 데이터를 분산시키는 방법으로 균일하게 분포된 데이터에 효과적이다. 즉 이력 데이터의 범위 분할 적용에서 나타나는 단점인, 각 범위(Bound)가 포함하는 데이터의 양이 일정하지 않아 분포도가 일정하지 않고 각 파티션의 크기가 다르게 나타나는 점을 개선한다. 이를 통해 일정한 분포를 가진 파티션으로 나누고 균등한 데이터 분포도를 이용한 병렬처리로 성능을 높인다.

리스트 파티셔닝(List Partitioning)은 로우를 파티션으로 맵핑하는 방법을 관리자가 명시적으로 설정할 수 있다. 관리자는 파티셔닝 컬럼을 위한 값의 리스트를 정의하는 방법으로 맵핑 방법을 설정한다. 컴포짓 파티셔닝(Composite partitioning)은 사용자가 다양한 파티셔닝 테크닉을 조합할 수 있도록 지원한다. 첫 번째 방법을 이용해서 테이블을 먼저 파티셔닝한 후 두 번째 방법을 통해 각 파티션을 다시 서브파티션으로 분할하는 것이다. 이때 인덱스는 크게 3가지 종류로 구분할 수 있다.

① 로컬 인덱스(Local Index) : 하부 파티션 테이블과 동일한 파티션 방법을 사용하여 파티셔닝된 테이블에 생성된 인덱스이다. 로컬 인덱스의 각 파티션은 하부 테이블의 특정 파티션에 맵핑된다.

② 글로벌 파티션드 인덱스(Global Partitioned Index) : 테이블의 서로 다른 파티셔닝-키를 이용해 파티션된 테이블이나 파티셔닝되지 않은 테이블에 생성된 인덱스를 가리킨다. 파티셔닝되지 않은 테이블의 인덱스와 동일한 형태로 구성되며 이때 인덱스 구조는 파티셔닝되지 않는다.


<표 4>는 오라클과 SQL 서버의 파티셔닝 옵션을 비교한 것이다. 오라클이 지원하는 다양한 파티셔닝 옵션을 확인할 수 있으며 실제 기능에 있어서도 <표 5>처럼 차이가 있음을 알 수 있다.

병렬 실행과 클러스터링
SQL 작업은 병렬 실행을 통해 대량의 데이터가 수반되는 작업의 성능을 크게 개선할 수 있다. 특히 의사결정 시스템 또는 데이터 웨어하우스 등의 대규모 데이터베이스에서 데이터 집중적인 작업을 수행할 때 응답시간 개선에 도움이 된다. 예를 들어 오라클 사용자가 SQL문에 대한 병렬 처리를 수행하고자 한다면 오라클 서버는 사용자의 요청에 따라 가용 가능한 CPU 개수 만큼 병렬 처리를 수행한다. 4개의 CPU를 가진 서버에서의 병렬 처리를 수행한다면 3개의 CPU에서 실 SQL문에 대해 균등하게 작업을 할당하여 처리하고 나머지 1개의 CPU에서 이를 병합하는 작업을 수행한다. 오라클 데이터베이스는 파티셔닝된 데이터베이스 오브젝트 또는 파티셔닝되지 않은 데이터베이스 오브젝트에 액세스하는 과정에서 INSERT, UPDATE, DELETE, MERGE 등의 구문을 병렬적으로 실행한다. 반면 SQL 서버 2005의 INSERT, UPDATE, DELETE 구문은 순차적으로 실행된다.

클러스터는 사설 네트워크를 통해 연결된 다수의 독립적인 서버 또는 노드들이 마치 하나의 시스템인 것처럼 협력하여 동작하는 환경을 의미한다. 단일 노드 시스템이 갖는 확장성의 한계를 극복하고 대형 서버의 성능을 뛰어넘는 부하 처리를 가능케 한다. 오라클 RAC(Real Application Cluster)이 바로 이런 역할을 지원하는 솔루션으로 DBMS에 대한 요구사항이 증가함에 따라 단순히 노드를 추가함으로써 확장할 수 있는 것이 특징이다.

SQL 서버 2000은 제품문서에 명시된 것처럼 이러한 형태의 클러스터링을 지원하지 않는다. 이것은 SQL 서버 2005에서도 마찬가지인데 대신 ‘Federated Database Server’라는 새로운 방식을 지원한다. 두 접근법은 매우 큰 차이를 갖고 있어 애플리케이션의 성능과 확장성에 큰 영향을 미칠 수 있다.

Federated Database Server는 독립적인 데이터베이스들로 구성되며 공통 데이터 딕셔너리와 글로벌 인덱스를 지원하지 않는다. 이 때문에 성능과 확장성 면에서 많은 제약이 따른다. 또한 SQL 서버 2005의 접근법은 실제 애플리케이션 환경에서 적용이 매우 힘들다. 실제로 SAP, 피플소프트 등의 비즈니스 애플리케이션은 일반적으로 수천 개의 테이블로 구성되는데 SQL 서버 2005의 Feder ated Database Server를 구현하려면 모든 테이블을 파티셔닝하거나 각 노드로 복제해야 한다. 이처럼 거대한 애플리케이션을 포팅하는 것은 복잡할뿐만 아니라 많은 비용을 필요로 한다.
<표 4> 오라클 SQL 서버의 파티셔닝 옵션 비교
파티셔닝 옵션 오라클 데이터베이스 10g 릴리즈 2 SQL 서버 2005
Range 지원 지원
Hash 지원 지원하지 않음
List 지원 지원
Composite 지원(Range-hashRange-list) 지원하지 않음
Local Index 지원 지원
Global Index 지원 지원

<표 5> 오라클 SQL 서버의 최대 파티션 수
  오라클 데이터베이스 10g 릴리즈 2 SQL 서버 2005
테이블 당 최대 파티션 수 1024K(100만 개 이상) 1000

반면 오라클 RAC는 상대적으로 포괄적인 애플리케이션 호환성을 제공한다. 대표적인 기업용 애플리케이션들을 효과적으로 확장할 수 있으며 클러스터링 환경을 위한 커스터마이즈 작업도 필요치 않다. 즉 데이터 액세스 패턴이 데이터 블럭 핑을 감소 또는 어렵게 하더라도 애플리케이션을 분할할 필요가 없다. 단일 노드의 오라클 서버에서 확장성 있는 애플리케이션은 멀티 노드의 RAC 상에서도 확장성이 있다. 이 때문에 기존 애플리케이션을 재설계하거나 코드를 수정할 필요가 없으며 애플리케이션을 명시적으로 분할하거나 데이터를 파티셔닝할 필요도 없다.

또한 SQL 서버는 파티션을 실제로 소유한 노드만이 해당 파티션에 대한 읽기 작업을 수행할 수 있다. 프로세싱 파워는 테이블이 포함된 노드의 프로세싱 파워로 한정된다. 그러나 오라클 데이터베이스에서는 이러한 제약이 존재하지 않으며 심지어 전체 시스템의 프로세싱 파워, 다시 말해 모든 병렬 실행 서버의 리소스를 이용해 하나의 파티션에 대한 처리 작업을 수행하는 것도 가능하다.



오라클 데이터베이스 10g vs. IBM DB2 UDB
지금까지 최근에 새로운 버전을 발표한 MS SQL 서버 2005와 오라클 데이터베이스 10g에 대해서 비교해 보았다. 이번엔 오라클과 IBM의 DB2를 역시 성능 관점에서 비교해보자. 두 제품을 본격적으로 비교하기에 앞서 여기서 사용되는 DB2, DB2 UDB 등의 용어는 모두 DB2 UDB ESE(엔터프라이즈 서버 에디션) Version 8.2를 가리킨다. 또한 오라클, 오라클 데이터베이스, 오라클 데이터베이스 10g는 모두 오라클 데이터베이스의 최신 버전인 오라클 데이터베이스 10g 엔터프라이즈 에디션 릴리즈 2를 의미한다.

동시성 모델
비교 항목은 역시 앞서 진행했던 것과 동일하다. 먼저 동시성 모델을 보면 오라클 데이터베이스와 IBM DB2는 동시성 컨트롤의 구현 방식에서 <표 6>과 같은 차이를 보인다. 오라클의 경우 쿼리와 업데이트가 동시에 발생하는 혼합형 워크로드 환경을 지원하며 쓰기 작업이 읽기 작업을 차단하거나 읽기 작업이 쓰기 작업을 차단하는 상황이 발생하지 않는다. 반면 DB2는 사용자가 정확성(accu racy)과 동시성(concurrency)의 두 가지 중 하나를 양자택일할 수밖에 없다. 즉 읽기 일관성을 보장하기 위해 쓰기 작업을 블로킹하거나 쓰기 작업을 차단하지 않는 대신 더티 리드(dirty read)로 인한 부정확한 결과를 감수해야 한다. 여기서 더티 리더란 언커밋 리더라고도 한다. 사용자가 변경시키고 있는 commit되지 않은 데이터를 다른 사용자가 읽는 현상을 말한다. 예를 들어서 A라는 사용자가 공유되어 있는 문서파일을 저장하지 않고 작성 중에 B 사용자가 이를 열어서 보는 현상을 들 수 있다.

오라클의 기본적인 아키텍처는 대용량 트랜잭션을 고려해 설계돼 있다. 이는 오라클이 특허를 보유한 논-에스컬레이팅 로우-레벨 락킹(non-escalating row-level locking) 기능(row에 대한 잠금을 가지는 lock이 이 잠금의 개수를 줄이기 위해서 상위 테이블 lock 등으로 확대시키지 않는 현상) 지원이 있기에 가능한 것인데, 애플리케이션에 연결되는 사용자의 수가 늘어나고 처리해야 하는 트랜잭션의 양이 증가해도 오라클 데이터베이스가 일관된 성능을 유지할 수 있는 것도 이 때문이다. Winter Corporation의 조사 결과 전세계적으로 가장 규모가 큰 상위 10개 유닉스 데이터베이스가 모두 오라클 기반으로 운영되고 있는 것 역시 효율적인 동시성 모델에 기인한 바가 크다.

DB2의 경우 락 정보의 추적을 위해 사용되는 메모리 구조의 용량이 제한되어 있기 때문에 트랜잭션 규모가 증가할 경우 리소스 사용량을 줄이기 위한 방편으로 로우 락(row lock)을 테이블 락(table lock)으로 에스컬레이션한다. 따라서 불필요한 경합이 발생하고 처리 성능의 저하가 일어날 수 있다.

오라클과 DB2 데이터베이스의 구현 방식은 멀티유저 환경에서 일반적으로 발생하는 다음과 같은 문제들을 방지하는 메커니즘에서도 큰 차이를 보인다. 참고로 여기서 non-repeatable read는 해당 트랜잭션 중 바로 전에 읽은 데이터가 다시 읽고 난 후 변경된 상태로, 첫 읽기 후 해당 데이터가 다른 트랜잭션에 의해 커밋된 상태를 의미한다. 또한 Phantom Read는 해당 트랜잭션 중 조건을 만족하는 튜플들을 리턴하는 쿼리를 재실행한 후 변경된 튜플들이 리턴될 때를 가리킨다.

트랜잭션이 커밋되지 않은 변경사항을 읽는 시점에 더티 리드(dirty read) 또는 언커밋트 리드(uncommited read)가 발생한다.

트랜잭션이 방금 전에 읽어 들인 데이터를 다시 읽는 과정에서 해당 데이터가 다른 커밋된 트랜잭션에 의해 수정되거나 삭제됐음을 확인했을 때 non-repeatable read가 발생한다.

트랜잭션이 검색 조건을 만족하는 일련의 로우를 반환하는 쿼리를 2차례 반복 실행하고 다른 애플리케이션에 의한 INSERT 작업으로 인해 두 번째 쿼리에서 (첫 번째 쿼리에서는 반환되지 않은) 추가적인 로우가 반환되었을 때 phantom read가 발생한다.


<표 6> 오라클과 DB2의 동시성 모델 기능 차이
오라클 데이터베이스 10g DB2 UDB
멀티-버전 읽기 일관성
(multi-version read consistency)
지원되지 않음
리드 락이 사용되지 않음 더티 리드를 방지하려면 리드 락이 필요
더티 리드를 사용하지 않음 리드 락을 사용하지 않는 경우 더티 리드 발생
로우-레벨 락(low-level locking)이 에스컬레이션 되지 않음 락이 에스컬레이션 발생
읽기 작업은 쓰기 작업을 블로킹하지 않음 읽기 작업이 쓰기 작업을 블로킹
쓰기 작업은 읽기 작업을 블로킹하지 않음 쓰기 작업이 읽기 작업을 블로킹
높은 부하에서 데드락이 전혀 발생하지 않음 높은 부하에서 데드락으로 인한 심각한 문제가 발생할 수 있음

오라클은 트랜잭션에 업데이트가 발생할 경우 기존 데이터는 데이터베이스의 언두 레코드에 저장된다. 데이터베이스가 읽기 작업을 수행하는 동안 데이터 변경을 방지하기 위해 또는 쿼리가 커밋되지 않은 변경 데이터를 읽는 것을 방지하기 위해 오라클은 락을 사용하는 대신 언두 레코드에 저장된 기존 정보를 이용하여 테이블 데이터에 대한 읽기 일관성을 확보한다. 반면 DB2는 멀티-버전 읽기 일관성을 제공하지 않는다. 대신 다양한 레벨의 격리 모델을 통해 읽기 잠금(read lock)을 사용하거나 더티 리드를 허용하는 방법을 사용한다. 읽기 잠금은 동시 수행 중인 트랜잭션에 의해 변경 중인 데이터를 읽을 수 없도록 차단하기 때문에 다수의 읽기/쓰기 작업이 동시에 발생하는 환경에서 서비스 동시 요청을 처리하는 능력이 제한될 수밖에 없다.

오라클이 지원하는 로우-레벨 락은 정교한 수준의 락 관리 방식으로 높은 데이터 동시성을 제공한다. 로우-레벨 락은 테이블의 특정 로우에 대한 업데이트 과정에서 해당 로우만을 잠금 처리하며 다른 모든 로우는 동시 작업이 가능하다. 오라클은 디폴트 동시성 모델로 로우-레벨 락을 사용하며 락 정보를 실제 로우 내부에 저장하고 이를 통해 데이터베이스의 로우 또는 인덱스 엔트리 숫자만큼 로우-레벨 락을 관리할 수 있게 해 데이터 동시성을 높였다.

DB2 역시 로우-레벨 락을 디폴트 동시성 모델로 지원한다. 그러나 DB2의 이전 버전에서는 로우-레벨 락이 기본 잠금 모드가 아니었고 후에 로우-레벨 락을 추가적으로 지원하는 과정에서 ‘락 리스트(lock list)’라는 별도의 메모리 구조가 필요하게 됐다. 이 메모리는 제한된 용량을 가지고 있으며 이 때문에 데이터베이스에서 지원할 수 있는 최대 락의 숫자 또한 제약된다. 이 때문에 애플리케이션과 트랜잭션 볼륨에 접근하는 사용자의 수가 증가하면 DB2는 메모리 절약을 위해 로우-레벨 락을 테이블 락(table lock)으로 에스컬레이션한다. 이는 결국 데이터에 동시 접근할 수 있는 사용자의 수가 줄어들게 됨을 의미하는데 그만큼 대기 시간이 길어질 가능성이 있다.
<표 7> 오라클과 DB2의 인덱싱 기능 비교
기능 오라클 DB2
Stored Compressed Bitmap Indexes 지원 -
비트맵 조인 인덱스 지원 -
다이나믹 비트맵 인덱스 지원 지원
IOT 지원 -
리버스 키 인덱스 지원 -
기능 기반 인덱스 지원 부분적으로 지원

실제로 DB2 매거진의 한 기사(www.db2mag.com/db_area/ archives/1999/q2/99sp_yevich.shtml)는 ‘락 에스컬레이션은 ERP 환경에서 가장 심각한 성능 저하 요인의 하나로 꼽힌다’고 지적하고 락 에스컬레이션을 비활성화할 것을 권고한 바 있다(그러나 이러한 작업은 OS/390 플랫폼의 DB2에서만 가능하며 유닉스와 윈도우 기반 DB2에서는 비활성화가 불가능하다).



인덱싱
오라클과 DB2는 모두 고전적인 B-트리 인덱싱 메커니즘을 지원한다. 이미 살펴본 것처럼 오라클은 이 밖에도 스태틱 비트맵 인덱스와 비트맵 조인 인덱스를 지원할 뿐만 아니라 여러 개의 파티션에 대한 글로벌 인덱스를 지원해 OLTP 환경의 파티셔닝된 테이블에서 유용하다. 반면 DB2는 B-트리 인덱스와 다이내믹 비트맵 인덱스 만을 지원한다. 두 제품의 인덱싱 기능 차이는 <표 7>과 같다.

오라클의 경우 인덱스는 대상 테이블의 하나 또는 그 이상의 컬럼에 대한 함수로 생성될 수 있다. 함수 기반 인덱스(function-based index)는 함수 또는 표현식의 결과를 미리 계산해 인덱스에 저장하며 B-트리 인덱스 또는 비트맵 인덱스로 생성할 수 있다. DB2의 generated column 기능의 경우 표현식을 기반으로 생성된 컬럼의 값을 유도한 결과가 인덱스에 저장된다. 그러나 유도된 값을 테이블 형태로 저장한다는 점에서 오라클의 함수 기반 인덱스만큼 효율적이지 못하다.

IOT는 테이블 로우를 프라이머리 키 인덱스에 저장하며 프라이머리 키에 대한 조건과 영역 검색을 수반하는 쿼리에서 높은 성능을 나타낸다. IOT를 이용하는 경우 중요 컬럼이 테이블과 프라이머리 키 인덱스에 이중으로 저장되지 않으므로 공간을 절약할 수 있고 일반적인 테이블에서 로우의 주소를 저장하고 인덱스 값과 로우 데이터에 대한 링크를 제공하는 용도로 사용되는 RowID를 위해 추가적인 공간을 할당할 필요도 없다. IOT는 기본키 인덱스 구조로 모든 데이터를 저장하므로 기본키 인덱스 스캔 만으로 모든 작업을 종료할 수 있다. 일반 테이블은 기본키를 사용하여 인덱스 스캔하여 해당 테이블로 랜덤 액세스를 수행하므로 IOT보다 성능 저하가 발생할 수 있다. 따라서 빠른 조회를 요구하는 OLTP 업무에서 IOT는 클러스터 테이블과 더불어 그 성능을 발휘한다.

IOT는 RowID pseudo-column, LOB, 2차 인덱스, range/hash 파티셔닝, 오브젝트 지원, 병렬 쿼리 등 일반적인 테이블에서 지원되는 모든 기능을 지원한다. IOT에 비트맵 인덱스를 생성하고 데이터 웨어하우징 환경의 팩트 테이블로 활용하는 것도 가능한데 이러한 기능은 오라클 데이터베이스 10g에서만 제공되는 기능이다.
파티셔닝
이미 살펴본 것처럼 파티셔닝은 대규모 데이터베이스를 관리하기 쉬운 단위로 분할하기 위해 사용되며 파티션 프루닝(partition pruning)이라 불리는 테크닉을 활용하는 경우 성능의 개선을 기대할 수 있다. 파티션 프루닝은 필요한 데이터가 존재하는 파티션에 대해서만 작업이 실행되도록 제한하는 기능을 말한다. 작업 과정에서 필요한 데이터를 포함하지 않은 파티션들은 검색 과정에서 제외된다. 이를 통해 디스크로부터 인출되는 데이터의 양과 프로세싱 시간을 크게 줄이고 쿼리 성능과 리소스 사용률을 개선할 수 있다.

파티셔닝 환경에서 partition-wise join 테크닉을 사용해 멀티-테이블 조인 작업의 성능을 개선할 수도 있다. 이것은 두 개의 테이블이 함께 조인되고 조인 키(join key)를 기준으로 두 테이블이 파티셔닝된 경우에 적용되는데 대규모 조인 작업을 각 파티션 별로 작은 크기의 조인 작업으로 분할하고 전체 조인 작업에 소요되는 시간을 단축하는 효과가 나타난다. 따라서 순차/병렬 작업 환경에서 성능 개선 효과를 기대할 수 있다. 마지막으로 파티셔닝 환경에서 DML 작업의 병렬 실행 기능을 활성화함으로써 데이터 집중적인 작업이 수반되는 대규모 의사결정 시스템이나 데이터 웨어하우스 환경의 응답시간을 단축할 수 있다.

이미 오라클에서 제공하는 파티셔닝은 살펴보았으므로 여기서는 DB2 UDB의 파티셔닝을 중점적으로 살펴보자. <표 8>은 두 제품의 파티셔닝 옵션을 비교한 것이다. DB2는 해시 파티셔닝만을 지원(ftp.software.ibm.com/ps/products/db2/info/vr8/pdf/letter/ db2s2e80.pdf)하기 때문에 오라클과 차이가 있음을 알 수 있다. 레인지 파티셔닝 또는 리스트 파티셔닝과 달리 해시 파티셔닝은 일부 쿼리에 대해 파티션 프루닝을 지원하지 않는다. 따라서 데이터 웨어하우스를 최신 상태로 유지하려면 새로운 데이터를 로드하고 오래된 데이터를 삭제하는 작업을 지속적으로 반복해야 하는 번거로움이 있다. 해시 파티셔닝이 적용된 DB2 환경에서는 전체 파티션에 대한 재분배 작업이 불가피하며 결과적으로 새로운 데이터를 로드하는데 더 많은 시간이 소요되고 데이터 재분배 과정의 테이블 잠금으로 인해 가용성이 저하될 가능성이 있다.

또한 DB2는 테이블과 인덱스 간의 ‘equi-partitioning’(인덱스가 같은 칼럼에 대해 같은 값으로 파티션되어 있는 것)을 요구하며 따라서 글로벌 인덱스의 생성이 불가능하다. 이러한 제약은 개별 레코드에 대한 효율적인 액세스를 위해 글로벌 인덱스를 빈번하게 활용해야 하는 OLTP 환경에서 심각한 문제를 야기할 가능성이 있다. 이처럼 DB2 기반의 애플리케이션 설계 과정에서는 파티셔닝 환경의 유연한 인덱스 구성이 어렵다(www-128.ibm.com/ developer works/db2/library/techarticle/dm-0405wilkins/ index.html).



클러스터
RAC은 오라클 데이터베이스 10g에 포함된 하드웨어 클러스터 지원 옵션이다. 이는 공유 디스크(shared disk) 방식을 채택하고 있는데 공유 디스크 아키텍처에서 데이터베이스 파일은 다수의 노드에 의해 논리적으로 공유되며 각 시스템의 인스턴스는 모든 데이터에 대한 접근이 허용된다. RAC 역시 오라클이 특허를 보유한 캐시 퓨전(Cache Fusion) 아키텍처를 기반으로 하고 있다. 캐시 퓨전은 상호 연결된 캐시를 이용해 OLTP, DSS, 패키지 애플리케이션 등 다양한 애플리케이션에 대한 데이터베이스 클러스터 기능을 지원한다. 사용자의 쿼리는 로컬 캐시 또는 다른 노드의 원격 캐시를 통해서도 처리할 수 있으며 업데이트 작업 과정에서 로컬 노드는 다른 클러스터 노드의 데이터베이스 캐시로부터 필요한 블럭을 직접 가져오므로 동기화를 위한 별도의 읽기/쓰기 작업을 수행할 필요가 없는 점도 특징이다.

반면 DB2는 Shared-Nothing 접근 방식을 사용한다. 이 아키텍처에서는 데이터베이스 파일이 파티셔닝을 통해 클러스터를 구성하는 각 노드의 인스턴스에 분산된 형태로 존재한다. 각 인스턴스 또는 노드는 일정 범위의 데이터만을 보유하며 해당 데이터를 배타적으로 점유하고 있다. 즉 Shared-Nothing 시스템은 파티셔닝을 통해 워크로드를 다수의 노드에 분산하는 효과를 제공하며 이것은 노드의 데이터 소유권이 자주 변경되지 않는 경우에 효과적이다(단 데이터베이스 재편성, 노드 장애시 데이터 소유권이 변경될 수 있다).

표면적으로는 Shared-Nothing 시스템이 분산형 데이터베이스와 유사하게 보인다. 그러나 Shared-Nothing 데이터베이스는 하나의 데이터 딕셔너리를 가진 하나의 물리적 데이터베이스라는 점에서 분산형 데이터베이스와는 근본적인 차이가 있다.

이미 살펴본 것처럼 오라클 데이터베이스 10g RAC은 패키지 애플리케이션을 별도의 수정 과정없이 단일 시스템에서 클러스터 구성으로 마이그레이션할 수 있다. 반면 DB2 데이터베이스를 DB2 UDB EEE로 마이그레이션하려면 데이터 파티셔닝 작업과 추가적인 개발 작업이 불가피하다. <표 9>는 두 제품의 아키텍처가 갖는 성능과 확장성 면에서의 차이를 비교한 것이다.
<표 7> 오라클과 DB2의 인덱싱 기능 비교
기능 오라클 DB2
레이지 파티셔닝 지원 -
리스트 파티셔닝 지원 -
해시 파티셔닝 지원 지원
컴포짓 파티셔닝 지원 -
로컬 인덱스 지원 지원
글로벌 파티션드 인덱스 지원 -
그로벌 넌 파티션드 인덱스 지원 -

오라클 데이터베이스 10g RAC은 트랜잭션을 실행 중인 노드에 로그를 기록하는 작업이 완료되는 즉시 커밋을 수행할 수 있다. 트랜잭션이 클러스터의 다른 노드에 의해 수정된 데이터를 접근해야 하는 경우에도 추가적인 디스크 I/O를 수반하지 않고 고속 연결을 통해 블럭을 전송한다. 로그의 쓰기 작업이 완료되지 않은 상태에서도 블럭을 전송할 수 있어 SAP SD 벤치마크처럼 집중적인 INSERT 작업이 수반되는 벤치마크 환경에서도 로그 쓰기 작업으로 인해 전송이 지연되는 경우가 5% 이하인 것으로 나타났다.

반면 DB2 시스템은 하나의 트랜잭션을 통해 두 개 이상의 파티션의 데이터가 변경된 경우 트랜잭션의 정합성을 보장하기 위해 two-phase 커밋 프로토콜(커밋 시점의 두 단계 커밋의 첫 번째 시점에 준비 레코드를 기록해야하며, 첫번째 단계를 완료해야 두 번째 단계를 진행하는 것)이 반드시 수행돼야 한다. DB2 트랜잭션은 커밋 시점에 쓰기 작업을 수행할 레코드를 미리 준비한 후 two-phase commit의 첫번째 단계를 완료한 이후에 두 번째 단계를 수행하며 이는 OLTP 애플리케이션의 응답시간을 저하시키는 결과를 초래할 수 있다.

RAC은 GCS(global cache service, 데이터가 필요하고 캐시에 여유 공간이 있는 RAC이 수정된 데이터를 독립적으로 캐시할 수 있게 해주는 서비스. 이 데이터에 대한 추가 액세스는 메인 메모리 속도로 수행할 수 있다)를 사용해 캐시 일관성을 보장한다. GCS는 RAC가 간헐적으로 변경되는 데이터를 여러 노드의 캐시에 동시에 저장하고 캐시를 위한 공간을 확보하기 때문에 이후 데이터에 대한 접근이 발생하는 경우 메인 메모리의 전송 속도에 준하는 응답시간을 나타낸다.

반면 DB2는 마지막 액세스가 발생한 이후 데이터가 변경되지 않은 경우에도 노드 간의 통신을 통해 다른 파티션의 데이터에 대한 접근을 처리한다. DB2는 인덱스와 테이블을 동일하게 파티셔닝하기 때문에 쿼리를 수행하는 과정에서 다수의 파티션에 대한 검색 작업이 불가피하다. 예를 들어 직원 테이블이 직원 번호를 기준으로 파티셔닝돼 있고 직원 이름을 기준으로 한 인덱스가 생성되어 있다면 직원 이름을 조회하는 쿼리를 수행하려면 모든 파티션을 동시에 검색해야 한다. 직원의 이름을 기준으로 한 조회 작업은 파티션의 수가 많으면 많을수록 높은 부하를 수반하게 된다.

또한 DB2 시스템은 특정 노드에 대한 부하 집중의 위험도가 높아 데이터가 전체 파티션에 균등하게 분산되어 있지 않을 수 있다. 예를 들어 금융계의 최근 거래내역의 빈번한 조회라든지 특정 데이터 영역대의 과도한 조회 업무에 따라 특정 파티션의 데이터가 집중적으로 조회될 가능성이 있다.
반면 RAC 환경에서는 개별 노드가 데이터를 점유하지 않으며 모든 노드가 동일한 데이터에 접근하므로 부하 분산의 불균형이 발생하지 않는다. 트랜잭션을 클러스터의 특정 노드군으로 라우팅함으로써 RAC의 성능을 더 높일 수 있으며 이를 통해 데이터 친화도(data affinity, 다량의 서로 다른 데이터에서 서로의 유사한 패턴)를 높이고 노드 간의 통신을 줄일 수 있다. 라우팅은 오라클 넷의 서비스 네임을 통해 간단하게 설정할 수 있다. 반면 DB2의 경우 트랜잭션에 의해 접근되는 데이터의 위치 정보가 별도로 필요하므로 트랜잭션의 라우팅이 훨씬 까다롭다. 또 데이터의 재분배 작업을 수행하지 않은 상태에서 다수의 논리적 노드에 트랜잭션을 수행해야 하므로 성능 저하 현상이 발생할 수 있고 부하의 변화에 유연하게 대처하지 못할 가능성이 높다.

<화면 1> ADDM을 통한 자가 튜닝 보고서

<화면 2> 튜닝 어드바이스
<표 9> 성능과 확장성 측면에서 오라클과 DB2 비교
오라클과 데이터베이스 10g RAC DB2 EEE
two-plase 커밋 불필요 two-plase 커밋 필요
데이터는 다수 노드의 캐시에 저장됨 다른 파티션에 접근하려는 경우 IPC 필요
데이터를 단 한 차례만 조회 다수의 파티션에 대해 데이터 조회
균등한 부하 분배 부하가 특정 노드에 집중될 가능성 높임

<표 10> 성능 관리 관련 기능 비교
  오라클 데이터베이스 10g DB2
성능 관련 관리 기능 - Automatic Workload Repository
- Automatic Database Diagnostic Monitor
- Automatic SQL Tuning
유사한 기능이 존재하지 않음

RAC은 애플리케이션의 바인드 값(bind value)를 기반으로 미들웨어가 요청을 라우팅하도록 구성되기도 한다. 예를 들어 사용자의 로그인 정보를 기반으로 메일 서버가 이메일 연결을 라우팅하도록 설정하는 식이다. 최적의 성능을 위해서는 레인지나 리스트 파티셔닝을 이용해 바인드 값을 기준으로 한 파티셔닝을 수행하는 것이다. 반면 DB2는 데이터의 위치를 사용자가 직접 결정할 수 없으므로 이와 같은 방식을 구현하기 힘들다.



셀프 튜닝과 성능 관련 기능
마지막으로 오라클과 DB2는 진단 및 셀프-튜닝 기능 측면에서도 차이가 있다. 오라클 데이터베이스 10g는 성능 모니터링 작업을 단순화하고 성능 문제의 진단과 해결을 자동화하기 위한 다양한 툴을 기본으로 지원해 이를 통해 시스템 리소스의 사용 상황에 따라 데이터 매개변수를 자동으로 조정한다. 관리자가 만일 어떠한 원인으로 일어날 수 있는지에 대한 시나리오를 시뮬레이션할 수 있는 인텔리전트 어드바이스 기능도 제공하는데 index advisory, summary advisory, memory advisory, MTTR advisory, table/index usage advisory 등이 대표적이다.

DB2 역시 일부 셀프-튜닝 기능과 어드바이스 기능을 제공하고 있지만 여전히 관리자에게 상당한 수준의 데이터베이스 지식을 요구한다. 예를 들어 DB2의 Control Center는 실시간 모니터링에 필요한 다양한 성능지표를 제공하지만 시스템의 전반적인 상태를 확인하기 위해 어떤 성능지표를 참고해야 하는지에 대한 정보는 알려주지 않는다. 알 수 없는 이유로 시스템의 성능이 저하된 경우 DB2 관리자는 전적으로 자신의 개인적인 지식에 의존해서 문제 해결 작업을 수행해야 하는 것이다. 반면 오라클은 어드바이스 기능을 이용하여 관리자에 대한 가이드를 제공하고, 도움말과 드릴다운을 통해 문제의 근본원인을 분석할 수 있도록 지원한다.

<표 10>은 오라클이 데이터베이스 튜닝 관련 정보를 제공하고 튜닝 프로세스 자동화를 위해 제공하는 기능을 요약한 것이다. AWR (Automatic Workload Repository)은 데이터베이스 작업에 관련한 성능 데이터와 통계를 저장하기 위해 활용되는 공간이다. 오라클 데이터베이스는 중요한 통계 정보와 워크로드 정보의 스냅 샷을 일정 주기로 생성하고 이를 AWR에 저장한다. 수집/처리된 통계정보는 오라클 데이터베이스 10g에 의해 사전 예방적/사후 대응적 모니터링을 위한 진단 데이터로 활용된다. 그러나 DB2는 이와 유사한 기능을 제공하지 않는다.

ADDM(Automatic Database Diagnostic Monitor)은 시스템 상태를 확인하기 위해 AWR에 캡처된 데이터를 분석하는 데이터베이스 자가진단 엔진이다. ADDM은 시스템의 어느 부분이 가장 많은 ‘DB time’을 사용하는지 분석하고 해결 방안을 제안하거나 SQL Access Advisor와 같은 다른 솔루션을 제안함으로써 DB time을 최소화하는 것을 기본 목적으로 하고 있다. ADDM은 표면적인 현상에 초점을 맞추는 대신 드릴다운을 통해 문제의 근본 원인을 확인하고 문제로 인한 시스템의 전반적인 영향에 대해 리포트를 제공한다. 또한 제시된 해결방안이 제공하는 기대효과를 정량화하고 성능에 문제가 없는 또는 튜닝이 불필요한 시스템 영역에 대한 보고서를 <화면 1>처럼 제공한다.

오라클 데이터베이스 10g는 SQL 구문의 튜닝 과정을 상당 부분 자동화했다. Automatic SQL Tuning은 Automatic Tuning Optimizer를 기반으로 구현된 기능으로, Oracle Query Optimizer는 자동 튜닝 모드에서 튜닝 프로세스에 필요한 조사와 검증 작업에 더 많은 시간을 할애한다. 이와 같은 추가적인 시간을 통해 다이내믹 샘플링, 부분 실행(partial execution) 등 일반 운영 모드에서는 시간적인 제약으로 인해 적용될 수 없었던 테크닉이 사용되며 비용, 선택성(selectivity)과 확률에 대한 검증 작업을 수행하는 것이 가능하다.

Automatic Tuning Optimizer에 의해 얻어진 결론은 SQL Tuning Advisor를 통해 튜닝 어드바이스의 형태로 사용자에게 전달된다. 어드바이스는 하나 또는 그 이상의 권고사항으로 구성되며 각 권고사항 별로 근거와 예상 효과가 명시된다. 어드바이스에는 새로운 인덱스의 추가, SQL 구문의 재작성, 또는 SQL 프로파일의 구현과 같은 내용이 포함될 수 있으며 사용자는 어드바이스의 이행 여부를 단순히 선택해 SQL 구문의 튜닝 과정을 완료할 수 있다. 반면 DB2는 SQL 관련 문제를 진단하기 위한 쉽고 편리한 방법을 제공하지 않으며 (오직 트레이스 기능만 제공) SQL 구문의 재작성을 통해 튜닝을 수행하는 툴 또한 제공하지 않는다.



오라클은 어렵다?
오라클 데이터베이스는 다양한 업계 표준/ISV 벤치마크를 통해 그 성능을 인정받고 있으며 이것은 가장 최근에 출시된 오라클 데이터베이스 10g 역시 예외는 아니다. 필자 역시 기존 버전 제품에서의 변화보다 더 많은 변화를 몸소 느끼고 있다.

이번 글에서는 다른 DBMS와 차이점을 중심으로 살펴보았지만 오라클 역시 타 DBMS에서 좋은 점들을 벤치마킹하기 위해 노력하고 있고 실례로 기존 버전에서 쉽게 손댈 수 없는 SQL 튜닝, 메모리 튜닝 등 자동화된 관리 기능은 초보자들도 쉽게 다룰 수 있도록 배려한 것으로 볼 수 있다. 즉 ‘오라클은 어렵다’는 등식도 점점 깨져가고 있는 것이다. 현재 국내에서 가장 널리 사용되고 있는 RDBMS인 오라클의 진화를 필자는 흥미진진한 마음으로 지켜보고 있다.



제공 : DB포탈사이트 DBguide.net

반응형
Posted by [PineTree]
DBMS2009. 7. 16. 11:04
반응형

많은 이들이 알고 있는 것처럼 다양한 소프트웨어 영역에서 오픈소스의 존재감과 활용도가 커지고 있고, 본격적으로 오픈소스의 도입을 고려하는 기업도 빠르게 증가하고 있다. 이 글에서는 미묘한 라이선스 정책의 차이점을 비롯해 오픈소스 도입을 고려하는 이들에게 도움이 될 만한 내용을 정리했다. 오픈소스 소프트웨어 중에서도 특히 DBMS의 라이선스 현황과 그에 따른 기술 지원 서비스에 대한 내용을 중점적으로 살펴보기로 한다.

 

2009년 경기 침체가 진행되는 가운데 IT 분야에서 가장 화두로 떠오른 것은 아마 오픈소스 소프트웨어가 아닐까 싶다. 가트너에 따르면 오픈소스 소프트웨어의 시장점유율은 2005년 11%(42.6억 달러)에서 2010년에는 24%(161.5억 달러)로 28.5% 성장할 것이며, 2010년까지 적어도 상용 소프트웨어 제품의 80%가 오픈소스 코드를 포함하게 될 것이라고 한다. 소스 코드가 공개되어 있어 소프트웨어를 무료로 사용할 수 있으므로 비용 절감이라는 장점이 있기도 하지만, 소스를 직접 수정하거나 변경해 사용할 수도 있기 때문에, 오픈소스 소프트웨어에 대한 관심은 날로 증가하고 있다. 그렇지만 오픈소스라 하여 아무런 제약이 없는 것은 아니다. 개발된 소스를 공개하는 과정에서 사용 제한을 두거나 조건이 있는 경우가 있다.

 

라이선스를 통해 본 오픈소스 DBMS

 

1990년대 무료 라이선스로 인식되는 몇몇의 소프트웨어들과 IBM, 썬(SUN)과 같은 대형 글로벌 벤더들의 참여로 개발자들 사이에 ‘자유(Free)’라는 단어가 무료라고 인식되면서, 사용자들 사이에 라이선스 오해로 인해 분쟁이 생겨났고, GPL 기반의 엄격한 라이선스 준수사항들 때문에 소프트웨어 개발에 대한 참여도가 떨어지기 시작했다. 1998년 이러한 시장 상황을 반영해 오픈소스 소프트웨어에 대해 OSI(Open Source Initiative)라는 단체가 결성되어 라이선스 체계를 정립하고, OSI에서 인증한 소프트웨어에 대해 OSI 인증 마크를 부여하기 시작했다.

 

라이선스에 대한 기본 정책은 오픈소스 소프트웨어 개발자가 만들어놓은 사용법과 조건에 따라 해당 소프트웨어를 사용하여야 하며, 위반할 경우 라이선스 위반으로 간주되는 동시에 저작권 침해로 인해 처벌을 받을 수 있게 된다. OSI가 정의한 라이선스 정책은 기본적으로 사용자의 자유로운 사용, 수정, 배포가 가능한 GPL(General Public License), LGPL(Lesser General Public License), BSD(Berkeley Software Distribution), MPL(Mozilla Public License) 이외에도 Apache 라이선스가 있다. OSI에 등록된 오픈소스 소프트웨어 중 대다수는 GPL과 LGPL, BSD 라이선스를 채택하고 있다.


<표 1>은 4개 라이선스에 대해 기술한 것으로, 무료 이용 가능, 배포 허용 가능, 소스 코드 취득 가능, 소스 코드 수정 가능 항목은 동일하나 2차 저작물 재공개 의무, 독점 소프트웨어와 결합 가능 항목에서는 각 라이선스마다 약간의 차이를 보인다. GPL의 경우, 2차 저작물 공개를 원칙으로 하여 독점 소프트웨어와 결합할 수 없으며, BSD는 2차 저작물 공개에서도 자유로울 뿐 아니라 독점 소프트웨어와도 결합이 가능한 그야말로 자유로운 방식이다.

 

<표 1> 라이선스의 형태 이해(출처: 컴퓨터프로그램보호위원회)

 

GPL을 채택하고 있는 대표적인 DBMS는 MySQL이지만 듀얼 라이선스 정책을 취하고 있다. GPL 라이선스가 적용된 커뮤니티 에디션(Community Edition)과 상용 라이선스인 엔터프라이즈 에디션(Enterprise Edition)이 있다. 최근 다우기술에서 MySQL과 함께 저변 확대를 꾀하고 있는 PostgreSQL의 경우, BSD 라이선스를 채택하고 있다. PostgreSQL 제품 기반의 사업을 전개하고 있는 EnterpriseDB사의 라이선스 정책은 오프소스 수익 모델인 Subscription 방식을 채택하고 있으며 ‘per socket’ 방식으로 가격이 책정되어 있다.

 

최근 NHN에 인수된 국내 오픈소스 DBMS인 CUBRID는 GPL 기반의 서버 엔진과 BSD 기반의 인터페이스 라이선스 정책을 채택하고 있다. MySQL의 경우, 응용프로그램을 개발하여 배포/판매하기 위해서는 응용프로그램 소스 코드를 오픈하거나 상용 라이선스를 구매해야 하는 반면, CUBRID의 경우에는 인터페이스와 서버를 나누어 두 가지 라이선스를 채택함으로써, 국내 독립 소프트웨어 벤더(ISV, Independent Software Vendor)가 CUBRID 2008 제품 기반의 응용프로그램을 개발하여 배포 및 판매하는 데 아무런 제약조건을 주지 않는다.

 

<표 2> 오픈소스 DBMS 라이선스 비교

 

그럼 실제 개발자나 사업자가 오픈소스 소프트웨어를 채택할 경우, 실제로 라이선스 정책에 위반이 되는지를 알아보기 위해 사용자 측면에서 상황에 따른 의문사항들을 시나리오별로 살펴보기로 하자.

 

시나리오로 본 라이선스 모델

 

라이브러리 링크

Q DBMS 인터페이스는 JDBC를 이용하고 있고 설치형 게시판을 만들고 싶다.

손수 만든 게시판을 다른 사람들도 사용할 수 있도록 나눠 주고 싶은데, 이런 경우에 내 소스 코드를 공개해야 하나? / CUBRID 기반의 중소기업용 전자결재시스템을 개발해서 판매하고 싶다. 우리 제품의 소스 코드를 공개하거나 상용 라이선스를 구매해야 할까?

 

A 위와 같이 DBMS가 제공하는 각종 라이브러리나 드라이버를 응용프로그램에서 링크해 사용하는 경우, JAVA 응용의 경우에는 JDBC 드라이버를, PHP 응용인 경우에는 PHP 인터페이스를 응용프로그램과 링크시켜야 한다. 이러한 경우에 MySQL을 사용하면 연결된 응용프로그램의 소스를 모두 공개하거나, 상용 라이선스를 구매해 소스를 공개하지 않을 수 있다. CUBRID는 응용과 연계되는 모든 인터페이스에 BSD 라이선스를 적용했기 때문에 응용프로그램의 소스를 공개할 필요가 없게 된다.

 

단순 호출일 경우

Q DBMS 백업 관리시스템을 만들어 사용해보고 쓸 만하면 제품으로 패키지해서 판매하고 싶다.

백업 관리시스템이기 때문에 DBMS 백업 파일을 다루거나 유틸리티(Utility)를 호출하는 방식으로 동작할 것이고 DBMS의 인터페이스나 라이브러리를 링크할 필요는 없다. 이런 경우에도 라이선스가 문제가 될까?

 

A 라이브러리나 드라이버를 응용프로그램과 직접 연결하지 않고 제공하는 기능을 단순하게 호출하는 경우에도, 라이브러리 링크와 마찬가지로 GPL 기반 DBMS를 사용하는 My SQL의 경우에는 상용 라이선스를 구매해야 하지만, CUBRID의 경우에는 소스 공개의 의무가 없다.

 

법인 간 배포

Q 한국에 본사가 있고 일본, 중국, 미국에 지사가 있는 기업이다.

본사에서 만든 게임으로 해외 법인에서도 서비스하고자 하는 데 가능한가?

 

A GPL 라이선스를 채택한 DBMS로 만든 응용프로그램을 서로 다른 법인 간에 배포하는 경우에는 응용프로그램의 소스를 모두 공개하거나 상용 라이선스를 구매해야 한다. 물론 CUBRID는 소스를 공개할 필요가 없다.

 

인터페이스 수정

Q DBMS가 제공하는 PHP 인터페이스에 개발 편의성을 위해 몇 가지 기능을 추가해야 한다.

PHP 인터페이스를 수정해서 사용하면 수정된 인터페이스나 연결된 응용을 모두 공개해야 할까?

AGPL 라이선스의 경우에는 소스에 수정을 가한 경우 해당 소스를 모두 공개해 개선된 기능을 다른 사용자들과 공유하는 것이 원칙이다. 하지만 CUBRID 경우에는 BSD 라이선스 정책이기 때문에 수정된 소스를 공개하지 않아도 된다.

 

서버 수정

 

추가적으로 DBMS 서버 엔진을 수정하고자 할 경우에는 MySQL뿐 아니라 CUBRID 역시 GPL 라이선스에 따라 소스 코드를 모두 공개해야 한다. 서버는 핵심 인프라이므로 개선된 기능을 많은 사용자들과 공유하는 것이 바람직하다는 생각 때문이다.

 

<그림 1> 워드 프로세서의 객체 종류

 

서비스로서의 오픈소스 소프트웨어

 

지난 2월 한국 소프트웨어 아키텍트 연합에서 실시한 설문조사에 따르면 오픈소스 소프트웨어를 전체 아키텍처의 25.0% 이하로 적용한다는 응답이 59.4%를 차지했고, 사용하지 않는다는 응답도 12.5%에 달했다. 오픈소스를 사용하지 않는 이유로는 기술 지원(77.4%), 안정성(58.15%), 기능적 성숙도(22.6%) 등에 대한 우려를 꼽았다. 포레스트 리서치(Forrest Research)에 따르면 오픈소스를 사용하지 않는 이유 중 기술 지원 부족이 답변 가운데 36%를 차지했다. 오픈소스가 갖는 장점에도 불구하고 많은 기업이나 개발자들이 적용하는 과정에 있어서 제품의 기술 지원에 따른 부담감을 안고 있음을 나타내는 증거라 할 수 있다.

 

이러한 시장 상황에 따라 최근 오픈소스 개발사들은 제품을 팔기보다는 제품을 얼마나 효율적으로 관리, 사용할 수 있느냐 하는 문제에 초점을 맞춰, 서비스 형태의 기술 지원을 제공하는 추세이다. 특히 DBMS와 같이 기업의 근간이 되는 인프라 소프트웨어인 경우 무엇보다 제품의 유지보수와 관리가 중요한 포인트인데, 라이선스 비즈니스 형태의 밀착력 있는 유지보수 정책에 길들여진 고객들이라면, 이러한 서비스 위주의 오픈소스 소프트웨어에 대해 반기지 않을 수 없을 것이다.

 

이러한 오픈소스 소프트웨어 업체들의 서비스 중심의 기술 지원은 고객의 요구사항에 따라 유연성 있게 부응할 수 있을 뿐 아니라, 고객 입장에서는 기존의 라이선스 구매에 따른 유지보수 비용에 비해 TCO(총 소유비용)를 절감할 수 있어, 오픈소스 소프트웨어가 갖는 한계점을 극복할 수 있게 되었다. 오픈소스 소프트웨어가 제공하는 서비스는 건마다 제공하는 단발성 기술 지원도 있지만 대부분은 1년 단위 서비스 계약을 통해 진행되는 것이 일반적이다. 유지보수 내의 기술 지원 항목으로는 패치, 업그레이드, 튜닝, 기술자문, 개발자 지원, 모니터링, 긴급 장애지원, 예방 및 점검, 운영 지원 등이 있다. 오픈소스 소프트웨어에서 제공하는 서비스들을 살펴보면 <표 3>과 같다.

 

<표 3> 오픈소스 소프트웨어의 제공 서비스

 

이 밖에도 큐브리드의 경우에는 지정 기술 인력을 배치하는 기술 어카운트 담당 서비스나 고객 지원 상황을 알려주는 트래킹 서비스 등을 제공하기도 한다. 트래킹 서비스란 고객이 요청한 서비스에 대해 접수부터 확인, 분석 과정 및 해결을 위해 적용하는 과정에 대해 실시간으로 확인할 수 있도록 도와주며, 특히 제품의 개선과 연관되는 경우에는 제품 개선 진행 상황 또한 실시간으로 확인 가능한 서비스를 말한다. 또한 진행 상황을 확인하여 완료시점(제품 개선의 경우, 제품의 공급시점)을 예측할 수 있어 더 빠른 의사 결정이 가능하도록 지원해준다. 제품의 안정성과 기술 지원 문제로 인해 기존의 오픈소스 소프트웨어들은 기업의 중대한 프로젝트에서 제외되는 경우가 많았는데, 최근 오픈소스 소프트웨어 개발사들의 이러한 기술 지원 체계들은 향후 오픈소스 소프트웨어의 도입과 적용에 적지 않은 영향을 줄 것으로 생각된다.

 

오픈소스 DBMS 적용 가속화

 

우리나라는 선진국에 비해 오픈소스 소프트웨어에 대한 관심과 자발적인 참여가 현저히 낮은 편이다. 그만큼 오픈소스 소프트웨어에 대한 인지가 늦었고 중요성을 뒤늦게 알기 시작했기 때문이다. 사실 우리나라에서 공개 소프트웨어가 알려지고 확산되기 시작한 것은 ‘2003년 1.25 인터넷 대란’ 이후부터라는 견해가 지배적이다. 그 결과, 2009년인 지금 30% 이상의 공공기관 서버에서 리눅스를 사용 중에 있고, 운영체제인 리눅스 외에 DBMS, WAS, 개발도구뿐 아니라 기업의 그룹웨어나 BPM 같은 솔루션들까지 다양한 분야로 확대되고 있다. 이에 발맞춰 정부도 공개 소프트웨어에 대한 확산과 개발자 참여를 유도하기 위해, 지식경제부는 지난해 기업과 대학이 함께 공개 소프트웨어 커뮤니티를 개최 및 운영해 소프트웨어 개발에 참여할 수 있도록 11개 커뮤니티를 지원했으며, 2009년에는 30개까지 확대했다. 정부 차원의 오픈소스 소프트웨어의 장려는 경제 불황에 따른 비용 절감 차원 측면에서도 생각할 수 있지만, 국내 소프트웨어 업계의 발전이라는 관점에서 오픈소스 개발자들의 참여 유도가 무엇보다 중요하다는 인식 때문으로 판단된다.

 

또한, 국내 포털 업체인 NHN뿐 아니라 씨디네트웍스, 삼성SDS, 유엔진 솔루션즈, 토마토시스템 등 다양한 분야에서 오픈소스 소프트웨어가 출시되기 시작했다. 게다가 네이버와 다음 등 대형 포털 업체들의 오픈 API 활성화를 위해 서비스를 본격화하기 시작했고 이러한 성과는 올해를 필두로 가시적인 변화를 가져올 것으로 기대된다. 이와 같이 국내 오픈소스 소프트웨어의 움직임이 활성화되고 있는 가운데, 오픈소스 DBMS의 사용과 적용 또한 점차적으로 확산될 것으로 예상된다.

 

DBMS 플랫폼의 다변화 예상

 

기업 내의 중요하지 않은 응용프로그램 요소에 오픈소스 DBMS가 채택되는 데는 2년 정도의 시간이 걸리지만, 그것이 중대한 프로젝트들로 확산되는 데는 약 5년 정도 걸리는 것으로 알려져 있다. 이에 근거할 때 오는 2012년에는 많은 기업들이 DBMS 플랫폼의 다변화를 꾀하리라 생각된다. 이는 단순 비용 절감이라는 측면에 그치는 것이 아니라, 소프트웨어 개발 환경을 활성화하고 자생력 있는 소프트웨어를 확산한다는 측면에서 접근하는 것이 바람직해 보인다.


다음 호에서는 특정 응용(게시판)을 중심으로 CUBRID와 타 DBMS와의 기능적 차이 및 구현방법 등을 점검해보기로 한다.

참고자료
1. http://kldp.org/files/open%20source%20guide.pdf
2. http://www.cubrid.com/zbxe/bbs_oss_guide
3. http://www.dt.co.kr/contents.htm?article_no=2009021702010860600004

 

필자소개

 

유명희 mhyu@cubrid.com|DBMS 마케팅 분야에서 다년간의 경험을 쌓았으며, 현재는 큐브리드에서 마케팅 팀장으로서 일하고 있다. 최근에는 국내 오픈소스 소프트웨어 시장에서 국산 DBMS의 저변 확대와 활성화를 위해 열심히 뛰고 있다.

 

출처 : 한국 마이크로 소프트웨어 [2009년 5월호]

제공 : DB포탈사이트 DBguide.net

반응형
Posted by [PineTree]