데이터베이스 키, 트랜잭션, 동시성 제어, MVCC, 인덱스

데이터베이스에서 다루는 데이터베이스 키, 트랜잭션, 동시성 제어, MVCC, 인덱스에 대해 알아봅니다.


데이터베이스

여러 사람에 공유되어 사용될 목적으로 저장하는 데이터의 집합

기본 용어

테이블 : 특정 데이터를 담기 위한 하나의 데이터 집합

  • 회원 테이블, 도서 테이블, 결제 테이블 등 레코드(= Tuple, Row) : 테이블에 저장된 데이터
  • 회원 테이블의 레코드 : 이름 + 전화 번호 + 주민등록번호 속성(= Column) : 레코드를 구성하는 각각의 열
    • 회원 테이블의 속성 : 이름, 전화 번호, 주민등록번호 도메인 : 속성이 취할 수 있는 같은 타입의 원자의 집합
    • 성별 테이블의 도메인 : 남, 여 기본키 : 레코드를 구분하는 기준이 되는 속성
    • 회원 테이블의 기본 키 : 주민등록번호 제약 : 속성의 기능을 한정시키는 것
    • 기본 키인 주민등록번호는 겹칠 수 없으며 빈 값이 들어갈 수 없음
    • 제약된 속성은 빠른 검색을 위해 내부적으로 인덱싱이 됨 (이진 트리로 정렬) 외래키 : 테이블의 관계를 표시하기 위한 속성
    • 도서 테이블에서 회원 테이블의 주민등록번호를 외래 키로 설정하여 대출 기록을 남김

테이블에서 각각의 다른 레코드와 구별할 수 있는 기준 key 슈퍼키 : 중복을 허용하지 않는 모든 속성들의 집합

  • 학생 테이블의 슈퍼키는 (학번), (주민등록번호), (학번, 주민등록번호) 이다 복합키 : 2개 이상의 속성을 조합하여 만든 속성들의 집합
  • 학생 테이블의 복합키는 (학번, 주민등록번호) 이다 후보키 : 유일성과 최소성을 모두 만족하는, 슈퍼키 중 최소성을 가지는 속성
  • 학생이라는 테이블이 있다면 후보키는 (학번), (주민등록번호) 이다 기본키 : 후보키 중에서 특별히 선정된 속성
  • 학생이라는 테이블이 있다면 기본키는 (학번) 또는 (주민등록번호) 를 선택할 수 있다 대체키 : 후보키 중에서 기본키가 아닌 속성
  • 학생이라는 테이블이 있다면 대체키는 (학번) 또는 (주민등록번호) 가 될 수 있다 (기본키에 따라 좌우됨) 외래키 : 다른 릴레이션의 속성을 참조하는 속성
  • 수강 테이블의 학번 속성은 학생 테이블의 학번 속성을 참조하여 값을 공유할 수 있다
  • 수강 테이블의 학번 속성에는 학생 테이블의 학번 속성에 없는 값을 입력할 수 없다
  • 수강 테이블의 학번 데이터가 존재하는 한, 학생 테이블을 삭제할 수 없다

테이블 관계

ONE TO ONE : 정확히 1대1로 매칭되는 형태

  • 유저 테이블과 유저 프로필 테이블 ONE TO MANY : 하나의 주체가 여러개의 레코드를 가질 수 있는 형태
  • 유저 테이블과 주문 기록 테이블 MANY TO MANY : ONE TO MANY TO ONE 의 형태
  • 유저 테이블과 주문 기록 테이블 + 상품 테이블과 주문 기록 테이블

트랜잭션

데이터베이스의 상태를 변화시키기 위해 수행하는 작업 단위

# 사용자 A가 사용자 B에게 만원을 송금한다 

* 이 때 생기는 DB 작업
- 1. 사용자 A의 계좌에서 만원을 차감한다 : UPDATE 문을 사용해 사용자 A의 잔고를 변경
- 2. 사용자 B의 계좌에 만원을 추가한다 : UPDATE 문을 사용해 사용자 B의 잔고를 변경

현재 작업 단위 : 출금 UPDATE + 입금 UPDATE
-> 이를 통틀어 하나의 트랜잭션이라고 한다
-> 두 쿼리문 모두 성공적으로 완료되어야 트랜잭션이 완료되는 것이다 "Commit"
-> 두 쿼리 중 하나라도 실패하면 모든 쿼리문을 취소하고 이전 상태로 되돌린다 "Rollback"

즉, 하나의 트랜잭션 설계를 잘 만드는 것이 데이터를 다룰 때 많은 이점을 가져다줍니다.

트랜젝션의 4가지 특징

  • 원자성(A) : 트랜잭션이 “Commit” 또는 “Rollback” 되어야 한다
    • 입금과 출금 중 하나만 처리된다면 원자성 위반이다
  • 일관성(C) : 트랜젝션의 작업 처리 결과는 항상 데이터의 일관성을 보장해야한다
    • 잔액이 없는데 출금이 가능해지면 일관성 위반이다
  • 고립성(I) : 각각의 트랜젝션은 서로 간섭없이 독립적으로 수행해야 한다
    • 출금과 입금이 동시에 수행되더라도 출금 -> 입금 처럼 수행한 것처럼 해야 한다
  • 지속성(D) : 트랜젝션이 성공적으로 완료되었으면, 결과는 영구적으로 반영되어야 한다

동시성 제어

동시성 제어란 DBMS가 다수의 사용자 사이에서 동시에 작용하는 다중 트랜잭션의 상호간섭 작용에서 Database를 보호하는 것을 의미합니다.
이렇듯 다수 사용자의 접속을 위해 동시성을 제어하는 방법에는 비관적 동시성 제어와 낙관적 동시성 제어가 있습니다.

비관적 동시성 제어

비관적 동시성 제어란 말 그대로 비관적으로 사용자들이 같은 데이터를 동시에 수정할 것이라고 가정하는 것입니다.
데이터를 읽는 시점에 Lock을 걸고, 트랜잭션이 완료될 때까지 이를 유지합니다. 때문에 정확도는 높지만 시스템 동시성을 심각하게 떨어뜨립니다.

낙관적 동시성 제어

낙관적 동시성 제어란 비관적 동시성 제어와 반대로 사용자들이 같은 데이터를 동시에 수정하지 않을 것이라고 가정하는 것입니다.
데이터를 읽는 시점에 Lock을 걸지 않는 대신 수정 시점에 값이 변경되었는지 반드시 검사합니다.

MVCC(Multi-Version Concurrency Control, 다중 버전 동시성 제어)

일반적인 Locking 매커니즘은 이러한 문제점을 해결하기 위해 MVCC가 등장하게 되었습니다.
MVCC 모델에서 데이터에 접근하는 사용자는 접근한 시점에서 데이터베이스의 Snapshot을 읽습니다. 이 Snapshot 데이터에 대한 트랜잭션이 commit되기 전까지 다른 데이터베이스 사용자는 볼 수 없습니다.
사용자가 데이터를 업데이트하면 이전 데이터에 덮어씌우는 것이 아닌 새로운 버전의 데이터를 이전 버전의 데이터와 비교하여 변경된 내용을 기록합니다.
이렇게 하나의 데이터에 대해 여러 버전의 데이터가 존재하게 되고, 사용자는 마지막 버전의 데이터를 읽게 됩니다.
이러한 구조를 지닌 MVCC의 특징을 정리하면 아래와 같습니다.

  • 일반적인 RDBMS보다 매우 빠르게 작동
  • 사용하지 않는 데이터가 계속 쌓이므로 데이터를 정리하는 시스템이 필요
  • 데이터 버전이 충돌하면 애플리케이션 영역에서 문제를 해결해야 함

인덱스

인덱스는 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조입니다.
책에서 원하는 내용이나 저자를 찾고자 할 때 색인을 추가하는데, 인덱스는 책의 색인과 같습니다.
인덱스를 활용하면, 데이터를 조회해야 하는 모든 쿼리의 성능이 향상됩니다. 만약 index를 사용하지 않은 컬럼을 조회해야 한다면 전체를 탐색하는 Full Scan을 수행해야 하는데, 이는 전체를 비교하여 탐색하므로 처리 속도가 떨어집니다.

인덱스 관리

DBMS는 index를 항상 최신의 상태로 유지하기 위해 INSERT, UPDATE, DELETE가 수행될 때 추가적인 연산을 해주어야 하며 그에 따른 오버헤드가 발생합니다.

  • INSERT: 새로운 데이터에 대한 인덱스를 추가
  • DELETE: 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업을 진행
  • UPDATE: 기존의 인덱스를 사용하지 않음 처리하고, 갱신된 데이터에 대해 인덱스를 추가

인덱스 장점

  • 테이블을 조회하는 속도가 빨라진다.
  • 데이터가 많을 경우 시스템의 부하를 줄일 수 있다.

인덱스 단점

  • 인덱스를 관리하기 위해 DB의 약 10%에 해당하는 저장공간이 필요하다.
  • 인덱스를 잘못 사용하면 오히려 성능에서 역효과가 난다.
    • 규모가 작지 않은 테이블과 데이터의 중복도가 낮은 컬럼에서 사용해야 한다.
  • 인덱스를 관리하기 위해 추가 작업이 필요하다.

해시 테이블

해시 테이블은 (key, value)로 데이터를 저장하는 자료구조 중 하나로 빠른 데이터 검색이 필요할 때 유용합니다. 해시 테이블은 key 값만을 사용해 고유한 index를 생성하여 그 index에 저장된 value값을 꺼내오는 방식입니다.
해시 테이블의 시간 복잡도는 O(1)으로, 매우 빠른 검색을 지원합니다.
하지만 해시는 등호(=) 연산에 특화되어 있기 때문에 부등호 연산이 자주 사용되는 데이터베이스 검색을 위해서는 해시 테이블이 적합하지 않습니다.
예를 들어 LIKE문을 사용하여 많은 데이터를 가지고 올 때, 만약 조회할 데이터가 많으면 많을수록 O(N)의 시간복잡도에 가까워지게 됩니다.

B 트리(B-Tree)

B 트리는 하나의 노드에 여러 데이터가 배치되는 자료구조이며, 어떤 값에 대해서도 같은 시간에 결과를 얻을 수 있게 보장되어 있습니다.
가장 상단의 노드를 루트 노드, 중간 노드를 브랜치 노드, 가장 하단 노드들을 리프 노드라고 합니다.
B 트리는 다른 트리와 달리 한 노드의 모든 데이터가 순차적으로 삽입되어 있으며 메모리에 연속적으로 저장되어 있습니다. 따라서 노드와 노드 사이는 참조로 이동하지만 노드 내부의 데이터는 순차적으로 이루어지므로 O(logN)의 시간복잡도를 가지는 트리 중에서도 물리적으로 더 빠르게 탐색할 수 있습니다.

image

B+ 트리(B+Tree)

B+ 트리는 자식 노드가 2개 이상인 B 트리를 개선시킨 자료구조이며, 모든 노드에 데이터를 저장하는 B 트리와 차이가 있습니다.
B 트리는 모든 노드가 data를 가진다면, B+ 트리는 리프 노드만 data를 가지고 있고 나머지 노드들은 데이터를 위한 인덱스만을 갖습니다. 또한 모든 리프노드가 LinkedList로 연결되어 있습니다. 따라서 B트리는 옆에 있는 리프 노드를 검사할 때, 다시 루트 노드를 통해 검사해야 한다면, B+ 트리는 선형 탐색을 통해 검사하므로 시간복잡도가 굉장히 줄어듭니다.

image

Categories:

Updated:

Leave a comment