데이터베이스 단원의 목차에 대해 설명드리겠습니다.
- SECTION 1 데이터베이스의 기본
- SECTION 2 ERD와 정규화 과정
- SECTION 3 트랜잭션과 무결성
- SECTION 4 데이터베이스의 종류
- SECTION 5 인덱스
- SECTION 6 조인의 종류
- SECTION 7 조인의 원리
4.1 데이터베이스의 기본
데이터베이스(DB, DataBase)는 여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합입니다. 해당 데이터베이스를 제어, 관리하는 통합 시스템을 DBMS(DataBase Management System)라고 하며, 데이터베이스 안에 있는 데이터들은 특정 DBMS마다 정의된 쿼리 언어(query language)를 통해 삽입, 삭제, 수정, 조회 등을 통해 수행할 수 있습니다. 또한, 데이터베이스는 실시간 접근 및 동시 공유가 가능할 뿐만 아니라, 삽입, 삭제 수정을 통해 최신 데이터를 유지할 수 있다는 장점이 있습니다.
DB <-> DBMS <-> 응용 프로그램의 구조에 따라서 데이터를 주고받게 됩니다. 예시를 들어, 응용 프로그램(Spring...)에서 DBMS(Mysql...)를 거쳐서 데이터베이스에 있는 데이터들을 가져다 쓸 수 있게 됩니다.
4.1.1 엔터티(entity)
엔터티는 업무에 필요하고 유용한 정보를 저장하고 관리하기 위한 집합적인 것(Thing)으로 정의됩니다.
하나의 엔터티는 2개 이상의 속성을 지니게 됩니다. 예를 들어, 회원이라는 엔터티는 이름, 아이디, 주소와 같은 속성을 같게 됩니다.
약한 엔티티 vs 강한 엔티티
A, B라는 엔터티가 존재할 경우, A 엔티티가 B에 존재여부에 따라 종속적이라면 A는 약한 엔터티가 되고, B는 강한 엔터티가 됩니다. 예를 들어, 냉장고는 집 안에만 존재하기 때문에 냉장고는 약한 엔터티가 되고, 집은 강한 엔티티라고 볼 수 있습니다.
4.1.2 릴레이션(relation)
릴레이션은 데이터베이스에서 정보를 구분하여 저장하는 기본 단위입니다. 데이터베이스에서 엔티티에 관한 데이터를 릴레이션 하나에 담아서 관리합니다.
4.1.3 속성
속성(attribute)은 DB를 구성하는 가장 작은 논리적 단위이며, 개체의 특성을 기술합니다. (회원 엔터티의 이름, 전화번호, 주소 등이 속성으로 볼 수 있습니다)
4.1.4 도메인
도메인(domain)이란 릴레이션에 포함된 각각의 속성들이 가질 수 있는 집합을 의미합니다. 학과라는 속성이 있으면, 속성에 대해 가질 수 있는 값은 {정보통신공학과, 컴퓨터공학과,...}입니다.
4.1.5 필드와 레코드
member_id, createdAt, modifiedAt, authority, email, nickname은 필드가 되고, 필드 아래 하나씩 쌓인 행 단위의 데이터를 레코드=튜플)라고 합니다.
4.1.6 관계
1:1, 1:N, N:M으로 구성
4.1.7 키
- 기본키 : 주 키 또는 프라이머리 키라고 부르며, 후보키 중에서 특별히 선정된 키로 중복된 값을 가질 수 없으며, 후보키의 성질을 가집니다.(최소성, 유일성 만족)
- 외래키 : 포린키라고 부르며, 다른 릴레이션의 기본키 필드를 참조하는 데이터의 참조 무결성을 확인하기 위해 사용되는 키
- 후보키 : 유일성과 최소성을 만족하는 속성 또는 속성들의 집합으로 튜플을 유일하게 구별하기 위해 꼭 필요한 속성들로만 이루어짐 (기본키의 후보)
- 대체키 : 후보키가 두 개 이상일 경우 어느 하나를 기본키로 지정하고 남은 후보키들을 의미합니다.
- 슈퍼키 : 각 레코드를 유일하게 식별할 수 있는 유일성을 갖춘 키입니다.
4.2 ERD와 정규화 과정
개체-관계 모델이란 구조화된 데이터에 대한 일련의 표현입니다. 릴레이션 간의 관계들을 정의한 것이며, DB를 구축할 때 기초적인 뼈대 역할입니다.
4.2.1 ERD의 중요성
요구사항을 기반으로 작성되기에, ERD를 기반으로 데이터베이스를 구축하게 됩니다. 데이터베이스 구축 이후에도 설계의 수정이 필요한 경우에 설계도 역할을 담당하기에, 굉장히 중요합니다.
다음과 같이, 요구 사항에 맞게 Erd를 작성할 수 있어야 합니다. 연관관계는 (User : Reply = 1 : N), (User : Board = 1 : N), (Board : Reply = 1 : N)입니다.
4.2.3 정규화 과정
- 정규형은 데이터베이스 설계에서 데이터의 중복, 이상 현상을 방지하고 데이터 일관성과 효율성을 유지하기 위해 적용되는 규칙들을 나타냅니다. 데이터를 구조화하여 테이블로 표현할 때, 정규형을 따르면 데이터의 중복을 최소화하고 데이터 조작의 효율성을 높일 수 있습니다.
정규형 원칙
- 같은 의미를 표현하는 릴레이션이지만, 좀 더 좋은 구조로 만들어야 하고, 자료의 중복성을 줄이고, 독립적인 관계는 별개의 릴레이션으로 표현이 가능해야 하는 것을 말합니다.
제1 정규형(First Normal Form, 1NF)
- 테이블의 컬럼들이 원자 값(Atomic value)을 가지고 중복이 없도록 설계되어야 함. 각 컬럼은 하나의 값만을 가지고, 그룹화된 값이나 반복 그룹이 포함되지 않아야 합니다.
user_id | username | subjects | archivement |
1 | seungbeom | {c++, c} | {90%, 10%} |
2 | junghwan | {java, javascript} | {50%, 50%} |
제1 정규형 적용
user_id | username | subjects | archivement |
1 | seungbeom | c++ | 90% |
2 | seungbeom | c | 10% |
3 | junghwan | java | 50% |
4 | junghwan | javascript | 50% |
제2 정규형(Second Normal Form, 2NF)
- 제2 정규형은 제1 정규형을 만족하면서 부분 함수 종속을 제거하는 것을 목표로 합니다. 부분 함수 종속이란 테이블의 기본 키가 아닌 속성이 기본키의 일부에만 종속되는 상황을 의미합니다.
user_id | username | subjects | archivement |
1 | seungbeom | c++ | 90% |
2 | seungbeom | c | 10% |
3 | junghwan | java | 50% |
4 | junghwan | javascript | 50% |
제2정규형 적용
user_id | username |
1 | seungbeom |
2 | junghwan |
username | subjects | archievement |
seungbeom | c++ | 90% |
seungbeom | c | 10% |
junghwan | java | 50% |
junghwan | javascript | 50% |
제3 정규형(Third Normal Form, 3NF)
- 제2 정규형을 만족하면서, 이행 함수 종속을 제거하는 것을 목표로 합니다. 이행 함수 종속이란 A->B, B->C인 함수 종속 관계에서 A->C인 함수 종속 관계를 의미합니다.
username | grade | top percentage |
taein | diamond | 5% |
seungbeom | platinum | 10% |
junghwan | master | 0.1% |
제3정규형 적용
username | grade |
taein | diamond |
seungbeom | platinum |
junghwan | master |
grade | top percentage |
diamond | 5% |
platinum | 10% |
junghwan | 0.1% |
보이스코드 정규형(Boyce-Codd Normal Form, BCNF)
- 제3 정규형을 만족하면서, 결정자 종속성을 제거하는 것을 목표로 합니다. 결정자 (X->Y, X는 결정자, Y는 종속자) 종속성이란 테이블의 비기본 키 컬럼이 기본키 컬럼을 결정하는 상황을 의미합니다. 즉, 후보키가 아닌 결정자를 제거하여 모든 결정자를 후보키로 만들어줘야 합니다.
학번 | 과목 | 강사 |
100 | DB | 홍길동 |
101 | C++ | 오정환 |
102 | C++ | 오정환 |
103 | DB | 홍길동 |
104 | DB | 홍길동 |
105 | Data Structure | 김철수 |
106 | C++ | 오정환 |
위에 명시한 릴레이션의 후보키는 학번 + 과목, 학번 + 강사입니다. 학번 + 과목은 강사를 결정하고, 강사는 과목을 결정합니다. 이러한 경우 삽입이상, 삭제이상, 갱신이상이 발생하게 됩니다. 만약, 김철수 강사도 C++ 과목을 담당한다고 가정했을 때, 김철수 강사의 C++과목을 수강하는 학생이 없으면 학번이 null이 되므로 삽입 이상이 생기게 됩니다. 학번이 105번인 학생이 김철수 과목을 철회한 경우, 김철수 강사가 Data Structure를 담당한다는 사실도 사라지므로 삭제이상이 생기게 됩니다. 더불어 오정환 강사가 C++에서 빅데이터분석으로 담당 과목을 변경했을 시, 해당 튜플을 3개를 모두 바꾸어줘야 하기 때문에 갱신이상도 발생하게 됩니다. 그래서 보이스코드/정규형을 적용시켜 이를 해결해야 합니다.
보이스코드 정규형 적용
학번 | 강사 |
100 | 홍길동 |
103 | 홍길동 |
104 | 홍길동 |
101 | 오정환 |
102 | 오정환 |
106 | 오정환 |
105 | 김철수 |
강사 | 과목 |
홍길동 | DB |
오정환 | C++ |
김철수 | Data Structure |
4.3 트랜잭션과 무결성
트랜잭션(transaction)이란 DB에서 하나의 논리적 기능을 수행하기 위한 최소 작업 단위입니다.
일반적으로 SQL(select, insert, delete, update)을 이용해서 DB에 접근하는데, 여러 개의 쿼리들을 하나로 묶는 단위를 말합니다.
트랜잭션의 ACID 원칙
ACID
- 원자성(Atomicity)
- 일관성(Consistency)
- 독립성(Isolation)
- 지속성(Durability)
원자성(Atomicity)
- 트랜잭션과 관련된 일이 모두 수행되었거나 되지 않아야 하는 all-or-nothing 방식입니다. 예를 들어 트랜잭션을 커밋했는데, 문제가 발생하여 롤백하는 경우 그 이후에 모두 수행되지 않음을 보장하는 말합니다.
A에서 B에게 500만 원을 송금하는 경우 (A 잔액 : 1000만 원, B 잔액 : 0원)
- A의 잔고 조회합니다.
- A에게서 500만 원을 뺀다.
- B에게 500만 원을 넣습니다.
사용자 관점에서 1 ~ 3 과정을 모두 볼 수도, 참여할 수도 없으며 단지, 결과(500만 원 송금 성공 및 실패)만 확인할 수 있습니다. all-or-nothing 방식인 이유는 만약 사용자가 작업을 취소한 경우, 다시 A의 잔액이 1000만 원이고, B의 잔액은 0원이어야 되기 때문입니다.
커밋 & 롤백
커밋(commit)
여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어입니다. 트랜잭션의 처리 과정을 DB에 반영하기 위해, 변경된 내용을 모두 영구적으로 저장합니다.
롤백(rollback)
트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 돌리는 일을 의미합니다. 변경 사항을 취소하고 트랜잭션 과정을 종료합니다.
커밋, 롤백이 존재하기에 데이터의 무결성을 보장할 수 있게 됩니다.
transaction Propagation
트랜잭션을 수행할 때, 커넥션 단위로 수행하기 때문에 커넥션 객체를 넘겨서 수행해야 합니다. 이를 매번 넘겨주기 번거롭기에 여러 트랜잭션 관련 메서드의 호출을 하나의 트랜잭션에 묶이도록 하는 것이 트랜잭션 전파라고 합니다.
Spring
@Transactional 트랜잭션 적용
- JPA의 모든 변경은 트랜잭션 안에서 이루어져야 합니다.
- 스프링 데이터 JPA가 제공하는 공통 인터페이스를 사용하면 데이터를 변경(등록, 수정, 삭제)하는 메서드에 @Transactional로 트랜잭션 처리가 됩니다.
- 따라서 서비스 계층에서 트랜잭션을 시작하지 않으면, 리포지토리에서 트랜잭션을 시작하고 서비스 계층에서 트랜잭션을 시작했으면 리포지토리도 해당 트랜잭션을 전파받아 그대로 사용
@Transactional(readOnly=true)
- 데이터를 조회하는 메서드에는 readOnly=true 옵션이 적용되어 있습니다.
- flush를 생략하므로 약간의 성능 향상을 얻게 됩니다.
트랜잭션 전파 설정
진행되고 있는 트랜잭션에 다른 트랜잭션이 호출되는 경우 처리 방법
1. REQUIRED(default)
부모 트랜잭션 존재 시 다른 트랜잭션이 부모 트랜잭션으로 합류, 그렇지 않으면 새로운 트랜잭션 생성, 롤백 발생 시 모두 롤백
2. REQUIREDS_NEW
무조건 새로운 트랜잭션을 생성. 각각의 트랜잭션이 롤백되더라도 서로 영향을 주지 않습니다.
3. MANDATORY
- 부모 트랜잭션에 합류하지만, 부모 트랜잭션 없을 경우 예외 발생
4. NESTED
- 부모 트랜잭션이 존재한다면, 중첩 트랜잭션 생성, 롤백 발생시 해당 중첩 트랜잭션의 시작 지점까지만 롤백, 중첩 트랜잭션은 부모 트랜잭션이 커밋될 때 같이 커밋됩니다.
- 부모 트랜잭션이 존재하지 않는 경우 새로운 트랜잭션 생성
5. NEVER
- 트랜잭션 생성 X, 부모 트랜잭션 생성 시 예외 발생
6. SUPPORTS
- 부모 트랜잭션이 있다면 합류, 없으면 트랜잭션 생성 X
7. NOT_SUPPORTED
- 부모 트랜잭션이 있다면 보류, 없으면 트랜잭션 생성 X
일관성(Consistency)
- DB에서 수행되는 트랜잭션이 데이터베이스의 일관된 상태를 유지해야 함을 의미합니다. 트랜잭션 수행 전후에 데이터베이스의 무결성 규칙이 지켜져야 한다는 것을 의미합니다. 즉, 트랜잭션의 수행 결과가 데이터베이스의 일관성을 깨뜨리지 않아야 합니다.
격리성(Isolation)
- 여러 트랜잭션이 동작할 때, 각 트랜잭션은 다른 트랜잭션에 영향을 받지 않고, 독립적으로 수행되어야 함을 의미합니다. 이는 동시에 실행되는 여러 트랜잭션 간에 서로 영향을 주지 않고, 각 트랜잭션이 마치 독립적으로 실행되는 것처럼 보이도록 해야 합니다. 격리성은 동시성 제어와 관련이 있으며, 트랜잭션의 동시 실행으로 인해 발생할 수 있는 문제들을 방지합니다.
지속성(Durability)
- 성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다는 것을 의미합니다. 즉, 트랜잭션이 커밋되면, 데이터베이스는 해당 변경 내용을 디스크나 영구 저장소에 영구적으로 저장해야 합니다. 이를 통해 시스템 장애 또는 전원 손실과 같은 문제가 발생하더라도 데이터의 손실을 최소화하고 데이터의 지속성을 보장합니다.
4.3.2 무결성
무결성
- 데이터의 정확성, 일관성, 유효성을 유지하는 것을 의미합니다.
- 위에 말씀드린 원자성, 일관성, 격리성, 지속성의 네 가지 특성을 가지면, 데이터의 일관성을 유지하고 동시 접근 제어, 회복 및 내구성을 보장합니다.
- 데이터베이스 시스템에서 데이터의 정확성과 신뢰성을 유지하며, 중요한 비즈니스 작업의 안정성과 지속성을 보장합니다.
종류
- 개체 무결성 : 기본키로 선택된 필드는 빈 값 X
- 참조 무결성 : 서로 참조 관계에 있는 두 테이블의 데이터는 항상 일관된 값 유지
- 고유 무결성 : 특정 속성에 고유한 값을 가지도록 조건이 주어진 경우, 그 속성 값은 모두 고유한 값을 지님
- NULL 무결성 : 특정 속성 값에 NULL이 올 수 없다는 조건이 주어진 경우, 그 속성 값은 NULL이 될 수 없다는 제약 조건
4.4 데이터베이스 종류
4.4.1 관계형 데이터베이스(RDBMS)
- 행과 열을 가지는 표 형식 데이터를 저장하는 데이터베이스
- SQL를 이용해 조작
- MySQL, PostgreSQL, Oracle, SQL Server 등이 있습니다.
stackoverflow 조사 결과
1. MySQL
- 대부분의 운영체제와 호환되며 가장 많이 사용하는 DB
- C, C++로 만들어졌으며, MylSAM 인덱스 압축기술, B-트리 기반의 인덱스, 스레드 기반의 메모리 할당 시스템, 매우 빠른 조인
- 대용량 DB를 위해서 설계되어 있고, rollback, commit, 이중 암호 지원 보안 등의 기능을 제공하며 많은 서비스에서 사용됩니다.
2. PostgreSQL
- MySQL 다음으로 많이 사용하는 DB
- 디스크 조각이 차지하는 영역을 회수할 수 있는 장치인 VACUUM을 가지고 있습니다.
- 최대 테이블의 크기는 32TB, SQL + JSON을 이용해 데이터에 접근할 수 있습니다.
4.4.2 NoSQL 데이터베이스
- SQL을 사용하지 않는 데이터베이스
1. MongoDB
- JSON을 통해 Data 접근, Binary JSON 형태로 데이터 저장
- 유연하고 확장 가능한 방식으로 다량의 데이터를 저장, 검색 및 관리하도록 설계
- 여러 서버에 데이터를 분산시키는 샤딩을 통해 수평적 확장성을 지원
- 빠른 읽기 및 쓰기 작업에 최적화되어 처리량이 많은 애플리케이션에 적합
- 풍부한 쿼리, 인덱싱 및 집계 파이프라인을 지원하는 강력한 쿼리 언어를 제공하여 효율적인 데이터 검색 및 분석이 가능
- 중복성과 자동 장애 조치를 제공하는 데이터베이스 서버의 자가 치유 클러스터인 복제 세트 지원
2. Redis
- 인메모리 DB, Key-Value 데이터 모델 기반의 DB
- 데이터 세트를 RAM에 보관하므로 매우 빠른 데이터 액세스 및 검색이 가능
- 데이터를 지속적으로 디스크에 저장할 수 있도록 하여 서버가 다시 시작되는 경우에도 지속성 제공
- Pub/Sub 메세징 : 발행/구독 메시징을 지원하여 애플리케이션의 서로 다른 부분이 서로 비동기적으로 통신할 수 있도록 합니다.
- 분산 캐싱 : 메모리 내 특성과 높은 읽기 및 쓰기를 처리하는 기능으로 인해 캐시로 사용
4.5 인덱스
4.5.1 인덱스의 필요성
인덱스
- 데이터를 빠르게 찾을 수 있는 하나의 장치
- 예시 : 책에 마지막 장에 있는 찾아보기 기능
4.5.2 B-트리
- 인덱스는 B-트리 자료구조 기반으로 이루어져 있습니다. 루트노드, 리프노드, 루트노드와 리프노드 사이에 있는 브랜치 노드로 나뉩니다.
- 트리 탐색은 맨 위 루트노드부터 탐색이 일어나며 브랜치 노드를 거쳐 리프 노드까지 내려옵니다. 그리고 데이터 포인터를 통해 결과값을 반환하게 됩니다.
- 인덱스가 효율적인 이유는 효율적인 단계를 거쳐 모든 요소에 접근할 수 있는 균형 잡힌 트리 구조와 트리 깊이의 대수확장성 때문입니다.
- 대수확장성 : 성장 속도 => 트리 깊이 < 리프 노드 수
4.6 조인의 종류
조인(join)이란 두 개 이상의 테이블을 묶어 하나의 결과물을 만드는 것을 의미합니다.
- 내부 조인(inner join) : 왼쪽 테이블과 오른쪽 테이블의 두 행이 모두 일치하는 행들만 반환하는 방식, 특정 열을 기준으로 두 테이블을 비교하고 조건에 맞는 행들만 결과로 반환, 이때, 기준 열의 값이 동일한 행들이 조인 결과로 반환 (교집합)
- 왼쪽 조인(left join) : 왼쪽 테이블의 모든 행과 오른쪽 테이블에서 일치하는 행들을 반환하는 방식, 왼쪽 테이블의 모든 행은 결과에 포함되며, 오른쪽 테이블에서 조건에 맞는 행이 없는 경우 NULL 값으로 채워짐
- 오른쪽 조인(right join) : 오른쪽 테이블의 모든 행과 왼쪽 테이블에서 일치하는 행들을 반환하는 방식, 오른쪽 테이블의 모든 행은 결과에 포함되며, 왼쪽 테이블에서 조건에 맞는 행이 없는 경우 NULL 값으로 채워짐
- 합집합 조인(full outer join) : 두 개의 테이블에서 모든 행들을 반환하는 조인 방식, 왼쪽 테이블과 오른쪽 테이블 양쪽의 모든 행을 결과에 포함시키며, 일치하는 행이 없는 경우에는 NULL 값으로 채워짐
<참고자료>
'CS' 카테고리의 다른 글
[CS] HTTP, HTTPS의 개념과 차이점에 대해 알아보자 (0) | 2023.12.01 |
---|---|
[CS] I/O 속도 개선을 위한 ios_base::sync_with_stdio(false), cin.tie(NULL), '\n' (1) | 2023.08.15 |
[컴퓨터 구조] chapter3 정리(컴퓨터 연산 : 부동소수점) (0) | 2023.05.28 |
[컴퓨터 구조] chapter3 정리 (컴퓨터 연산 : 덧셈, 뺄셈, 곱셈, 나눗셈) (0) | 2023.05.22 |
[CS] 복잡도, 선형 자료 구조, 비선형 자료 구조 (0) | 2023.05.20 |