by-nc-sa     개발자, DBA가 함께 만들어가는 구루비 지식창고!

성능향상을 위해서는 튜닝하지 말고 디자인하라




  • "튜닝"은 SQL 쿼리 또는 데이터 모델을 가리킬 수 있다.
    이 장에서 언급하고 싶은 것은 데이터 모델을 서투르게 디자인하면 그 어떤 SQL 튜닝도 도움이 되지 않는 것이다.

6.1 일반적인 데이터 모델을 사용하지 말라

  • 애플리케이션이 "최상의 융통성"을 위해 일반적인 데이터 모델 위에 구축되거나 성능에 저해되는 방식으로 구축되는 것은 드문 일이 아니다.
    예를 들어, 네 개의 테이블을 이용하여 거의 모든 객체를 데이터베이스에 표현할 수 있다
    create table objects ( 
     oid int primary key
    ,name varchar2(255) 
    );
    create table attributes (
     attrId int primary key
    ,attrName varchar2(255)
    ,datatype varchar2(25)
    );
    create table object_Attributes (
     oid int
    ,attrId int
    ,value varchar2(4000)
    ,primary key (oid, attrId)
    );
    create table Links (
     oid1 int
    ,oid2 int
    ,primary key (oid1, oid2)
    );
    
    insert into attributes values ( 1, 'DATE_OF_BIRTH', 'DATE' );
    insert into attributes values ( 2, 'FIRST_NAME', 'STRING' );
    insert into attributes values ( 3, 'LAST_NAME', 'STRING' );
    commit;
    
    insert into objects values ( 1, 'PERSON' );
    insert into object_Attributes values( 1, 1, '15-mar-1965' );
    insert into object_Attributes values( 1, 2, 'Thomas' );
    insert into object_Attributes values( 1, 3, 'Kyte' );
    commit;
    insert into objects values ( 2, 'PERSON' );
    insert into object_Attributes values( 2, 1, '21-oct-1968' );
    insert into object_Attributes values( 2, 2, 'John' );
    insert into object_Attributes values( 2, 3, 'Smith' );
    commit;
    
    -- 모든 PERSON 레코드의 FIRST_NAME과 LAST_NAME을 가져오는 질의
    select max( decode( attrName, 'FIRST_NAME', value, null ) ) first_name
          ,max( decode( attrName, 'LAST_NAME', value, null ) ) last_name
      from objects
          ,object_attributes
          ,attributes
     where attributes.attrName in ( 'FIRST_NAME', 'LAST_NAME' )
       and object_attributes.attrId = attributes.attrId
       and object_attributes.oid    = objects.oid
       and objects.name             = 'PERSON'
     group by objects.oid;
    




    더 이상 테이블을 생성할 필요가 없다. 필요한 경우(ATTRIBUTES 테이블에 삽입함으로써) 즉시 열을 추가할 수 있기 때문이다.
    개발자는 제 마음대로 할 수 있으며 DBA는 이들을 제지할 수도 없다. 유연성이 극대화된 셈이다.
    그렇다면 이 모델의 성능은 어떠하겠는가? 비참, 처참, 끔찍 그 자체이다.
    이 모델에서는 쿼리 작성이 쉬워 보일 수 있다.
    예를 들면, 3월에 태어났거나 성이 스미스인 모든 사람들을 조회하고 싶다면
    모든 PERSON 레코드의 FIRST_NAME과 LAST_NAME을 구하는 쿼리를 작성하고 그 주위를 인라인 뷰로 감싸면 된다.

    select *
      from ( select max( decode( attrName, 'FIRST_NAME', value, null ) ) first_name
                   ,max( decode( attrName, 'LAST_NAME', value, null ) ) last_name
                   ,max( decode( attrName, 'DATE_OF_BIRTH', value, null ) ) date_of_birth
               from objects
                   ,object_attributes
                   ,attributes
              where attributes.attrName in ( 'FIRST_NAME', 'LAST_NAME', 'DATE_OF_BIRTH' )
                and object_attributes.attrId = attributes.attrId
                and object_attributes.oid    = objects.oid
                and objects.name             = 'PERSON'
             group by objects.oid
           )
     where last_name = 'Smith'
        or date_of_birth like '%-mar-%';
    


    쿼리가 쉬워 보인다면 성능에 관하여 생각해 보라! 몇 천 개의 OBJECT 레코드와 수만 개의 OBJECT_ATTRIBUTES가 존재한다고 가정해 보면
    오라클은 첫 번째 쿼리를 통해 전체 내부 그룹을 처리하고 WHERE 절을 적용할 것이다.

6.2 효율성을 염두에 두고 데이터 모델을 디자인하라

  • 데이터 모델은 가장 빈번하게 발생하는 쿼리에 대해 가장 효율적으로 응답할 수 있도록 디자인되어야 한다.
  • 처음부터 원활한 수행을 목표로 시스템은 디자인하므로 디자인 및 구현 과정에서 정확하게 예측할 수 없을 경우에만 튜닝을 실시한다.

6.2.1 쓰기 또는 읽기 위주로 디자인할까?

  • 팜 모델을 이용한 웹 기반의 내부용 달력 시스템 구축 사례

6.2.2 어느 모델이 효과적이었을까?

  • 사용자의 요구를 데이터 모델에 맞추는 것이 아니라 데이터 모델을 사용자의 요구에 맞추자

문서에 대하여

문서정보

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.