'Database'에 해당되는 글 3건

  1. 2015.09.02 데이터베이스의 인덱스 자료구조 B-TREE 2
  2. 2015.09.02 트리거(Trigger)
  3. 2015.08.11 데이터베이스 정규화 4

인덱스??

데이터베이스의 사전목차와 같은 것으로 인덱스를 컬럼에 걸어주게 되면 검색 성능이 향상된다. 


인덱스는 무조건 쓰면 좋은가??

인덱스의 간단한 특징에 대해서 설명해보자면, 인덱스를 생성해주면 특정 컬럼에 대해 검색 성능이 향상된다. 

반면에, 인덱스를 위해 사용되어지는 추가적인 메모리 공간이 필요하고, INSERT, UPDATE, DELETE 시 기존의 데이터베이스 정보 뿐만 아니라, 인덱스 정보도 갱신해주어야 하기 때문에 성능이 떨어질 수 있다.

한 마디로 검색 성능과 삽입삭제성능의 트레이드오프(Trade-Off)관계!!


인덱스는 어떻게 이루어져있나?

내부적으로 여러 방식으로 구현하지만, 제일 보편적인 것이 B-Tree 인덱스이다.


B-Tree인덱스는 브랜치 블록(Branch Block)과 리프 블록(Leaf Block)으로 이루어진다. 브랜치 블록의 가장 최상위 노드를 루트 블록(Root Block)이라고 한다. 

브랜치 블록은 분기를 위한 목적으로 활용된다. 브랜치 블록은 다음 단계를 가리키는 포인터를 가지고 있다. 

리프 블록은 인덱스를 구성하는 컬럼의 데이터와 해당 데이터를 가지고 있는 행의 위치를 가리키는 레코드 식별자(RID, Record Indentifier/Rowid)로 구성되어 있다. 인덱스는 인덱스를 구성하는 컬럼의 값으로 정렬되어 있다. 리프블록은 양방향 링크(Double Link)를 가지고 있어, 오름차순, 내림차순으로 검색이 가능한 것이다. 

B-Tree 인덱스는 "="으로 검색하는 일치(Exact Match)검색과 "Between", ">"와 같은 연산자로 검색하는 범위(Range)검색 모두에 적합한 구조이다. 


B-Tree 인덱스가 구체적으로 어떻게 검색하는 것인가??

그렇다면 이러한 B-Tree를 이용해서 어떻게 데이터를 쉽게 찾아내는지에 대해서 그림을  보면서 설명하겠다.

1단계, 브랜치 블록의 가장 왼쪽 값이 찾고자 하는 값보다 작거나 같으면 왼쪽 포인터로 이동

2단계, 찾고자 하는 값이 브랜치 블록의 값 사이에 존재하면 가운데 포인터로 이동

3단계, 오른쪽에 있는 값보다 크면 오른쪽 포인터로 이동


예를 들어 37의 값을 찾고 싶다면??

37을 찾고자 한다면 루트블록에서  50보다 작으므로 왼쪽 포인터로 이동한다.

37는 왼쪽 브랜치 블록의 11과 40 사이의 값이므로 가운데 포인터로 이동한다.

이동한 결과 해당 블록이 리프블록이므로 37이 블록 내에서 존재하는지 검색한다. 


또 예를 들어 만약 37~50의 값을 찾고 싶다면??

앞에서와 같이 37을 찾은다음에 정렬되어 있는 링크를 따라 50까지 검색해주면 된다. 완전 좋다!









'Database' 카테고리의 다른 글

트리거(Trigger)  (0) 2015.09.02
데이터베이스 정규화  (4) 2015.08.11
Posted by slender ankles
,

트리거(Trigger)

Database 2015. 9. 2. 01:36

트리거란?


<<ORACLE>>

// 트리거 예제
CREATE OR REPLACE Trigger SUMMARY_SALES                // (1)
    AFTER INSERT
    ON ORDER_LIST
    FOR EACH ROW
DECLARE                                                // (2)
    o_date ORDER_LIST.order_date%TYPE;
    o_prod ORDER_LIST.product%TYPE;
BEGIN
    o_date := :NEW.order_date;
    o_prod := :NEW.product;
    UPDATE SALES_PER_DATE                            // (3)
        SET qty = qty + :NEW.qty, amount = amount + :NEW.amount
    WHERE sale_date = o_date
        AND product = o_prod;
    if SQL%NOTFOUND    THEN                            // (4)
        INSERT INTO SALES SALES_PER_DATE
        VALUES(o_date, o_prod, :NEW.qty, :NEW.amount);
    end if;
END;
 
(1) Trigger를 선언한다.
CREATE OR REPLACE Trigger SUMMARY_SALES => 트리거 선언문
AFTER INSERT    => 레코드가 입력된 후 트리거 발생
ON ORDER_LIST    => ORDER_LIST 테이블에 Trigger 설정
FOR EACH ROW    => 각 ROW마다 Trigger 적용
(2) o_date(주문일자), o_prod(주문상품) 값을 저장할 변수를 선언하고, 신규로 입력된 데이터를 저장한다.
: NEW는 신규로 입력된 레코드의 정보를 가지고 있는 구조체
: OLD는 수정, 삭제되기 전의 레코드를 가지고 있는 구조체
(3) 먼저 입력된 주문 내역의 주문 일자와 주문 상품을 기준으로 SALES_PER_DATE테이블에 업데이트한다.
(4) 처리 겨로가가 SQL%NOTFOUND이면 해당 주문 일자의 주문 상품 실적이 존재하지 않으며, SALES_PER_DATE
    테이블에 새로운 집계 데이터를 입력한다. 
cs


'Database' 카테고리의 다른 글

데이터베이스의 인덱스 자료구조 B-TREE  (2) 2015.09.02
데이터베이스 정규화  (4) 2015.08.11
Posted by slender ankles
,

데이터베이스의 정규화란 무엇이며, 왜 필요한가?

데이터베이스의 정규화란 관계형 데이터베이스를 설계할 때나오는 개념입니다. 

관계형 데이터베이스란 쉽게 말해서 실제 존재하는 개념을 개체(Entity)로 만들어 개체간의 관계(Relationship)를 만들어주는 것을 말합니다. 

학생이라는 Entity와 관계(Relation)된 Entity에 대해서 예를 들어보자면 스터디그룹, 전공학과일 것입니다. 

이렇게 각 개체와 개체간의 관계를 테이블 등으로 표현하는 것을 데이터베이스라고 합니다. 


예를 들어 학교라는 시스템을 데이터베이스로 표현한다면 우선 학생이란 개체(Entity)가 필요할 것입니다. 

학생이라는 Entity에는 <이름>, <나이>, <학번>, <전공>과 같은 속성들을 가지게 될 것입니다. 

이를 토대로 학생 테이블에 데이터가 구성하게 되면 

 이름

나이 

학번 

전공 

 김아무개

21 

201501012 

컴퓨터공 

이런식의 하나의 표, 그러니까 테이블이 만들어 질 것입니다. 

김아무개 뿐만 아니라 홍길동의 데이터가 추가되면 김아무개의 다음 행에 홍길동과 함께 한 행을 채우게 되겠죠. 

여기서 학생이라는 개념을 테이블(다른 말로, 릴레이션, Relation)

이름, 나이, 학번, 전공를 열(다른 말로, 어트리뷰트, Attribute)

그리고 김아무개의 정보가 담긴 한 행을(다른 말로, 튜플, Tuple)이라고 합니다. 

또, 전공이라는 열을 예로 들어보면 컴퓨터공, 경영학, 기계공학... 등등 채워질 수 있는 내용들이 있게 됩니다.

이 속성을 이루는 값들의 집합을 도메인(Domain)이라고 합 니다. 

테이블 = 릴레이션, 열 = 어트리뷰트 .... 짜증납니다. 똑같은 개념에 대한 단어가 여러 가지입니다. 


아무튼 이렇게 누구나 알 법한 데이터베이스에 대한 기초상식에 대해서 이야기 한 이유는 

데이터베이스를 설계하면서 필요한 정규화의 개념에 대해서 이야기하고 싶어서 입니다.

학생 테이블 뿐만 아니라 수강생 테이블을 하나 더 생각해봅니다. 

수강생 테이블에는 

<학번>, <이름>, <나이>, <전공>, <재수강여부> 등등의 정보가 들어갈 수 있겠죠

학번 

이름 

나이 

전공 

재수강여부 

201501012

김아무개 

21 

컴퓨터공 

True

201502039

홍길동

22 

경영학과 

False


뭔가 비효율적이지 않나요?

학교 시스템이라는 전체 시스템에서 학생, 수강생의 예만 들어봐도 저렇게 중복되는 정보가 있습니다. 

<학번>, <이름>, <나이>, <전공> 등은 학생 테이블이나 수강생 테이블에 중복되어 존재하게 됩니다. 

그렇지만 학생이라는 객체와 수강생이라는 객체는 엄연히 분리되어 할 개념이긴 한데 말이죠.

비효율적이라고 말한 이유는 간단합니다. 테이블이 수정되거나 삽입 될 때에는 모든 테이블에 걸쳐서 연쇄적으로 수정되거나 삽입되어야 합니다. 단 두가지의 테이블만 봐서 그렇지 어떠한 시스템에서는 이런식으로 데이터베이스가 짜져있다면 최소 수십개의 테이블에 데이터를 삽입하던지 수정해야 될 것입니다. 데이터의 일관성을 유지하기 위해서 말이죠. 


이러한 상황을 해결하기 위해 정규화(Nomalization) 라는 것이 필요한 것입니다. 

기본적으로 정규화란 잘못설계된 데이터베이스의 구조를 더 작은 속성으로 쪼개어 바람직한 구조로 만드는 과정입니다. 

* 여기서 번외로 하나 설명해보자면, 결국 정규화 과정을 거치게 되면서 한데 뭉쳐있던 테이블을 더 잘게 쪼개게 되어 테이블의 수가 더 많아지게 됩니다. 이렇게 쪼개어진 정보에서 의미있는 정보를 추출해내기 위해서는 서로 합치는 과정을 통해 출력 결과를 도출해내는 연산이 필요한데, 이를 관계형 데이터베이스에서는 JOIN이라고 부릅니다. 이 JOIN 연산시 상당히 큰 부하를 가져오게 됩니다. 물론 그렇다고 정규화를 안한 데이터베이스를 사용하진 않습니다. 보통 성능과 이상증상의 제거를 고려하여 적당한 선에 결정합니다.(Trade Off)


정규화의 방법에는 여러가지가 있습니다. 

1NF, 2NF, 3NF, BCNF, 4NF, 5NF 등 많이 있으나 (NF = Normal Form, 정규형) 성능상의 이슈등을 고려해 보통 3NF나 BCNF정도에서 멈춘다고 합니다. 

(성능을 위해 이미 정규화된 테이블을 합치는 것을 역정규화라고 합니다)


제1 정규화(= 1NF)

모든 속성은 원자값을 가진다. 하나의 컬럼에는 두 개의 값이 들어 갈 수 없다는 것입니다. 

이름

취미

니콜라스

자전거, 독서

위의 테이블은 니콜라스라는 사람이 가지는 취미가 자전거, 독서인데, 한 컬럼에 두 개의 값이 들어가있습니다. 이러한 구조는 제1정규화의 대상입니다. 다음과 같이 수정합니다.

이름

취미

니콜라스

자전거

니콜라스

독서


제2 정규화(= 2NF)

Key 외의 다른 컬럼들은 Key에만 의존적이어야 한다. (완전 함수 의존) 

이 말이 처음에는 잘 이해가 안됐는데, 쉽게 정리해보자면 

키(중심이자 유일한 성질을 갖는 컬럼) 이외의 일부 컬럼에 의해 결정되는 컬럼들이 있으면 

안된다는 말이다. 

예를 들어 학교라는 테이블을 생각해보자.

<"학교"테이블>

학번

학생이름

학년

학과

수강과목

학점

교수

개설학과

key값이 학번, 수강과목에 있다. 학번과 수강과목을 통해 행의 유일성은 보장 할 수 있겠지만 제2정규화를 만족할 수 없다. (키에 의존적이지 않은 컬럼들이 존재한다)

학생이름과 학년 학과는 학번에 종속적인 컬럼입니다. 종속적이라는 것은 학번이라는 값을 통해 결정되는 컬럼을 뜻합니다.

의존적이라는 말이 오히려 더 이해하기 쉬운 듯하지만 혼용해서 사용하겠습니다. 

이에 반해 학점, 교수, 개설학과는 수강과목에 종속적인 컬림입니다. 결국 학점, 교수, 개설학과는은 학번에 의존적인 컬럼이 아니라는 이야기입니다. 마찬가지로 학생이름, 학년, 학과도 수강과목에 의존적이지 않은 컬림이죠.

다음과 같이 수정해야 합니다.

<"학생"테이블>

학번

학생이름

학년

학과


<"수강과목"테이블>

수강과목

학점

교수

개설학과

<"수강"테이블>

학번

수강과목

이와같이 변하면 각 컬럼들은 해당 테이블의 키값에만 종속적이게 됩니다.

제3 정규화(= 3NF)

기본키에 의존하지 않고, 일반키에 의존적인 컬럼들을 제거합니다.

보통 책에는

"이행종속이 있으면 안된다. 단, Key가 아닌 어느 속성이 Key의 일부를 결정지을 수 있다면 3NF를 만족"

"이행종속이란? A->B, B->C 결정하는 경우 A->C를 결정" 이렇게 설명되어 있는데

이게 도대체 무슨말인가...싶습니다. 쉽게 이해가 되지 않습니다. 

첫 번째 줄이 더 이해 잘 될 것 같습니다. 


기본키에 의존하는 키에 또 다른 컬럼이 의존하는 것. 즉 A -> B, B -> C 와 같이 설명한 것을 이해할 수 있겠습니다.


제2정규화된 결과에서 수강과목 테이블에 주목합니다. 수강과목 학점 교수 개설학과로 이루어져 있습니다. 

교수는 수강과목에 의존적인 테이블 컬럼이고, 개설학과는 교수에 의존적인 테이블 컬럼입니다. 즉, 제3정규화의 대상이라는 말입니다. 다음과 같이 바꾸어줍니다. 

<"학생"테이블>

학번

학생이름

학년

학과

<"수강과목"테이블>

수강과목

학점

교수

<"교수"테이블>

교수

개설학과

<"수강"테이블>

학번

수강과목


이렇게 하면 3NF를 만족한다.(이행종속이 없다)


BCNF

BCNF의 주요 내용은 모든 결정자는 반드시 Key이어야 한다는 것입니다. 

1NF에서 곧 바로 BCNF 정규화가 가능합니다. 

학번 -> 이름, 학년, 학과

과목 -> 학점, 교수

교수 -> 개설학과

이렇게 키를 규정할 수가 있습니다. 


제 4정규화

함수종속이 아닌 다치 종속 제거


제 5정규화

후보키를 통하지 않은 조인 종속성을 제거






'Database' 카테고리의 다른 글

데이터베이스의 인덱스 자료구조 B-TREE  (2) 2015.09.02
트리거(Trigger)  (0) 2015.09.02
Posted by slender ankles
,