From a6c1e5a52d491c626cecf6e1ca41f803983ddae0 Mon Sep 17 00:00:00 2001 From: Minjoo Date: Thu, 28 Nov 2024 14:06:59 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EB=94=94=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DB/minjoo522.md | 392 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 DB/minjoo522.md diff --git a/DB/minjoo522.md b/DB/minjoo522.md new file mode 100644 index 0000000..120a1cd --- /dev/null +++ b/DB/minjoo522.md @@ -0,0 +1,392 @@ +### 데이터베이스에서 인덱스를 사용하는 이유와 장단점 + +- 인덱스 : 데이터베이스 테이블의 특정 컬럼에 대해 정렬된 구ㅗ를 제공해 검색 속도 향상 / 빠르게 원하는 데이터를 찾을 수 있다. +- 장점 : 검색 속도 향상, 정렬 효율 +- 단점 : 쓰기 성능 저하(인덱스를 유지하기 위해 추가 연산 발생), 추가 저장 공간 필요 + +### InnoDB 인덱스 구조 + +- B+Tree 기반 구조 + - 정렬된 키-값 구조 + - 리프 노드들이 더블 링크드 리스트로 연결되어 있어 검색이나 순차적인 데이터 읽기에 유리하다. : 리프 노드들이 서로 앞뒤로 연결되어 있어 빠르게 순차적으로 접근할 수 있다. + - 균형 상태를 유지해 삽입, 삭제 후에도 일정한 성능을 보장한다. +- 클러스터형 인덱스(Primary key) / 보조 인덱스(Secondary Index) +- 클러스터형 인덱스(Clustered Index) + - 기본 키를 기준으로 데이터를 정렬하고 저장 + - 기본 키가 없으면 내부적으로 6-byte의 숨겨진 클러스터 키를 생성해 이를 기반으로 데이터 저장 및 정렬 + - 인덱스 노드 리프에는 실제 테이블의 행 데이터가 저장된다. + - 클러스터형 인덱스를 통해 데이터에 바로 접근할 수 있다. + - 테이블 당 하나만 만들 수 있다. +- 보조 인덱스(Secondary Index) + - 특정 컬럼에 대한 검색 기능 향상 + - 리프 노트에 해당 컬럼 값 + 클러스터형 인덱스 키 값이 저장된다. + - 보조 인덱스를 사용한 후 클러스터형 인덱스를 통해 실제 데이터를 가져온다 : 백트래킹 / 커버링 인덱스 + - 하나의 테이블에 여러개 생성할 수 있다. +- 장점 + - 빠른 데이터 검색 + - 효율적인 정렬 및 범위 검색 +- 단점 + - 쓰기 작업 비용 증가 + - 추가 저장 공간 + +### InnoDB 버퍼 풀, REDO로그, UNDO로그 + +- 데이터베이스 성능과 데이터 무결성을 보장하는 중요한 역할을 한다. +- **InnoDB 버퍼 풀** + - 메모리 영역 + - 디스크 I/O를 줄이고 데이터 읽기/쓰기 성능을 향상시키기 위해 사용된다. + - 데이터 페이지, 인덱스 페이지, 변경된 데이터를 디스크로 쓰기 전에 임시로 저장하는 캐시 역할 + - 변경된 데이터를 모아서 일괄 처리로 디스크에 기록한다. -> 동일한 데이터를 여러 번 변경해도 디스크에 중복적으로 쓰지 않고 버퍼 풀에서만 갱신된다. + - 데이터 캐싱 + - 자주 읽히는 데이터와 인덱스 페이지를 메모리에 유지해 디스크 접근 횟수를 줄인다. + - 쓰기 지연 + - 데이터 변경은 즉시 디스크에 기록되지 않고, 버퍼 풀에 저장된 후 나중에 디스크에 기록 된다 -> 쓰기 성능 향상 + - 데이터 변경 작업이 있을 때마다 디스크에 즉시 반영하면 쓰기 작업이 병목이 된다. + - 변경된 데이터는 **더티 페이지**로 표시된다 : 메모리에서 수정되었지만 아직 디스크에 반영되지 않은 페이지 + - LRU 알고리즘 + - 자주 사용되는 데이터를 오래 유지하기 위해 LRU(Least Recently Used) 알고리즘을 사용한다. -> 자주 사용되지 않는 데이터는 메모리에서 제거된다. +- **REDO 로그** + - 지속성을 보장하기 위한 로그 / 장애 복구를 위해 사용된다 + - 커밋된 변경사항을 복구하거나 디스크에 기록되지 않은 변경 사항을 재적용한다. + - 어떤 데이터 페이지에서 어떤 부분이 어떻게 수정되었는지 기록한다. + - 쓰기 성능 향상 + - 변경 사항은 데이터 파일에 직접 기록되지 않고, REDO 로그에 먼저 기록된 후, 비동기로 데이터 파일에 쓰여진다. + - 쓰기 작업 속도를 높이고, 디스크 I/O 부하를 줄인다. + - 복구 기능 + - 장애 발생 -> REDO 로그를 이용해 마지막으로 커밋된 상태로 복구할 수 있다. + - WAL(Write-Ahead Logging) 방식 + - 데이터를 디스크에 쓰기 전에 REDO 로그를 먼저 기록한다. -> 데이터 무결성 보장 + - 고정 크기 순환 버퍼(circular buffer) : 로그 파일이 가득 차면 오래된 로그를 덮어쓴다. + - 디스크에 할당된 고정된 크기의 로그 파일로 저장된다. + - 덮어쓰기는 순차적으로 반복되며 계속 순환한다. +- **UNDO 로그** + - 롤백이나 MVCC(Multi-Version Concurrency Control, 다중 버전 동시성 제어)를 지원하기 위해 사용한다. + - 트랜잭션이 데이터 변경 전에 해당 **데이터 원본 값**을 기록한다. + - 롤백 + - 트랜잭션 도중 오류가 발생하거나 명시적으로 롤백이 요청되면 UNDO 로그를 이용해 데이터를 변경 이전 상태로 복원한다. + - 변경 이전 데이터를 UNDO 로그에 저장하고, 이를 사용해 원래 데이터를 복구한다. + - MVCC 지원 + - UNDO 로그에 이전 데이터 버전을 저장해 읽기 작업이 트랜잭션의 스냅샷을 사용할 수 있도록 한다. + - 지연된 변경 기록 + - 트랜잭션이 완료되기 전까지는 UNDO 로그를 통해 변경 내용이 롤백될 수 있다. -> 데이터 파일에는 즉시 기록되지 않는다. + +#### 데이터 변경 과정 (버퍼 풀, UNDO 로그, REDO 로그 병렬 처리) + +- 데이터 변경 요청이 들어오면, InnoDB는 먼저 데이터를 메모리 **버퍼 풀**에서 변경한다. +- 변경 전에 원래 데이터를 **UNDO 로그**에 저장한다. +- 변경 내용은 **REDO 로그**에 기록되어 디스크로 최종 기록을 보장한다. +- 일정 주기 또는 체크포인트 시점에 변경된 데이터는 디스크로 플러시 된다. + +### 트랜잭션이란? + +- 데이터베이스에서 일련의 연속적인 작업들을 하나의 단위로 묶어서 처리하는 개념 +- 데이터베이스의 정합성을 유지하고 작업의 원자성을 보장하기 위해서 사용된다. +- ACID + - 원자성(Atomicity) + - 트랜잭션 내의 모든 작업은 하나의 단위로 처리된다. + - 트랜잭션이 시작되면 모든 작업이 완료되거나, 하나라도 실패하면 모든 작업이 취소된다. + - 일관성(Consistency) + - 트랜잭션이 완료되면 데이터베이스는 일관된 상태로 유지된다. + - 트랜잭션이 실행되기 전과 후, 데이터베이스는 정의된 규칙을 충족하는 상태 + 데이터 무결성 보장 (**제약 조건 만족**) + - 격리성(Isolation) + - 각 트랜잭션은 서로 독립적으로 실행되어야 한다. + - 지속성(Durability) + - 트랜잭션이 완료되면 그 결과는 영구적으로 저장되어야 한다. + +### 트랜잭션 격리 수준 + +- 데이터베이스에서 동시에 실행되는 트랜잭션들이 서로 간섭하지 않고 독립적으로 수행되도록 보장하는 방법 +- 데이터의 일관성과 정확성을 유지하면서 여러 트랜잭션에 동시에 실행될 수 있도록 돕는다. +- 하나의 트랜잭션이 다른 트랜잭션의 작업에 영향을 미치는 경우를 의미한다. +- READ UNCOMMITTED + - 하나의 트랜잭션애서 수정한 데이터가 아직 커밋되지 않았더라도 다른 트랜잭션이 이를 읽을 수 있다. + - Dirty Read가 발생할 수 있다. +- READ COMMITTED + - 한 트랜잭션이 커밋한 후에만 다른 트랜잭션이 그 값을 읽을 수 있다. + - Non-Repeatable Read가 발생할 수 있다. +- REPEATABLE READ + - 트랜잭션이 시작된 이후 읽은 데이터는 변경되지 않으며 다른 트랜잭션이 이를 수정할 수 없다. + - 동일한 쿼리로 반복해서 조회할 경우 항상 같은 결과를 받는다. + - Phantom Read가 발생할 수 있다. +- SERIALIZABLE + - 가장 높은 격리 수준 + - 트랜잭션이 순차적으로 실행되는 것처럼 등장한다. + - 한 트랜잭션이 완료될 때까지 다른 트랜잭션이 실행되지 않는다. + - 성능 저하 / 병목 현상이 발생할 수 있다. + +### MySQL의 Repeatable Read에서의 Phantom Read + +- MVCC, Next-Key Lock으로 Phantom Read를 방지한다. +- MVCC + - 언두로그를 통해 대부분의 Phantom Read 상황을 커버할 수 있다. + - `SELECT .. FOR UPDATE`(선택한 행들을 잠금, 갭 잠금)를 실행하면 Phantom Read가 발생한다 -> 언두 레코드에는 Lock을 걸 수 없기 때문에 현재 레코드의 값을 가져오기 때문이다. +- Next-Key Lock + - Gap Lock + Record Lock + +### 데이터베이스 정규화란? + +- 데이터베이스 설계에서 데이터를 중복 없이 효율적으로 저장하기 위한 과정 +- 목표 : 데이터 중복을 최소화하고 데이터의 일관성과 무결성을 유지하기 +- 데이터를 여러 개의 관련된 테이블로 나누는 방법을 사용한다. + +#### 1차 정규형(1NF: First Normal Form) + +- 테이블 내 모든 컬럼이 원자값을 가져야 한다. +- 각 컬럼에 들어가는 데이터는 더 이상 나눠지지 않는 단일값, 배열이나 리스트는 허용되지 않는다. +- 잘못된 예 + +| 학생 ID | 이름 | 전화번호 | +| ------- | ------ | ------------------ | +| 1 | 홍길동 | 010-1234, 010-5678 | +| 2 | 김영희 | 010-9876 | + +- 올바른 예 + +| 학생 ID | 이름 | 전화번호 | +| ------- | ------ | -------- | +| 1 | 홍길동 | 010-1234 | +| 1 | 홍길동 | 010-5678 | +| 2 | 김영희 | 010-9876 | + +#### 2차 정규형(2NF: Second Normal Form) + +- 1NF를 만족 + 부분 함수 종속(Partial Dependency)을 제거하는 규칙 +- 기본키에 대해 모든 비기본 컬럼이 전체 기본키에 종속, 기본키의 일부에만 종속되는 컬럼은 별도의 테이블로 분리해야 한다. +- 잘못된 예 + +| 학생 ID | 과목 ID | 교수 이름 | +| ------- | ------- | --------- | +| 1 | 101 | 김 교수 | +| 1 | 102 | 이 교수 | +| 2 | 101 | 김 교수 | + +- (학생 ID, 과목 ID) 복합키 -> 교수 이름은 과목 ID에만 의존한다. +- 학생 ID는 교수 이름에 영향을 미치지 않기 때문에 학생 ID가 교수 이름에 의존하는 것은 **부분 함수 종속**이다. + +- 올바른 예 +- 학생 테이블 + +| 학생 ID | 과목 ID | +| ------- | ------- | +| 1 | 101 | +| 1 | 102 | +| 2 | 101 | + +- 교수 테이블 + +| 과목 ID | 교수 이름 | +| ------- | --------- | +| 101 | 김 교수 | +| 102 | 이 교수 | + +#### 3차 정규형(3NF: Third Normal Form) + +- 2NF를 만족 + 이행적 함수 종속(Transitive Dependency)을 제거하는 규칙 +- 기본키와 관계없는 컬럼은 다른 컬럼에 의존하지 않아야 한다. +- 모든 비기본 컬럼은 기본키에만 의존해야 한다. +- 잘못된 예 + +| 직원 ID | 이름 | 부서 | 부서장 | +| ------- | ------ | ------ | ------- | +| 1 | 홍길동 | 개발 | 김 부장 | +| 2 | 김영희 | 마케팅 | 이 과장 | + +- 부서장 -> 부서 / 부서 -> 직원 ID +- 부서장은 직원 ID와 관계 없이 부서에 의존 + +- 올바른 예 +- 직원 테이블 + +| 직원 ID | 이름 | 부서 | +| ------- | ------ | ------ | +| 1 | 홍길동 | 개발 | +| 2 | 김영희 | 마케팅 | + +- 부서 테이블 + +| 부서 | 부서장 | +| ------ | ------- | +| 개발 | 김 부장 | +| 마케팅 | 이 과장 | + +- 부서장은 부서에만 의존한다. + +#### 보이스-코드 정규형(BCNF: Boyce-Codd Normal Form) + +- 3NF를 만족 + 기본키가 아닌 속성이 다른 비기본 속성에 의존하지 않도록하는 규칙 +- 모든 결정자가 후보키여야 한다. +- 잘못된 예 + +| 학생 ID | 과목 ID | 교수 이름 | +| ------- | ------- | --------- | +| 1 | 101 | 김 교수 | +| 2 | 101 | 김 교수 | + +- 과목 ID가 교수 이름을 결정하고 있다 -> 과목 ID 기본키 ❌ + +- 올바른 예 +- 과목 테이블 + +| 과목 ID | 교수 이름 | +| ------- | --------- | +| 101 | 김 교수 | + +- 학생 테이블 + +| 학생 ID | 과목 ID | +| ------- | ------- | +| 1 | 101 | +| 2 | 101 | + +#### 4차 정규형(4NF: Fourth Normal Form) + +- 다중 값 종속(Multi-valued Dependency)을 제거하는 규칙 +- 하나의 컬럼이 두 개 이상의 독립적인 값을 가질 수 없도록 한다. +- 잘못된 예 + +| 학생 ID | 전화번호 | 이메일 | +| ------- | -------- | ------------ | +| 1 | 010-1234 | student1@abc | +| 1 | 010-5678 | student1@xyz | + +- 학생 ID에 대해 전화번호와 이메일이 독립적으로 여러 값을 가질 수 있다. -> 같은 테이블에서 관리하는 것은 4NF 위반 + +- 올바른 예 +- 학생 테이블 + +| 학생 ID | 전화번호 | +| ------- | -------- | +| 1 | 010-1234 | +| 1 | 010-5678 | + +- 학생 이메일 테이블 + +| 학생 ID | 이메일 | +| ------- | ------------ | +| 1 | student1@abc | +| 1 | student1@xyz | + +#### 5차 정규형(5NF: Fifth Normal Form) + +- 조인 종속성을 제거 +- 테이블이 분해되어도 원래의 데이터를 다시 복원할 수 있어야 하며, 여러 테이블을 조인해도 데이터 손실이 없어야 한다. +- 잘못된 예 + +| 학생 ID | 과목 ID | 교수 ID | 교수 이름 | +| ------- | ------- | ------- | --------- | +| 1 | 101 | 201 | 김 교수 | +| 1 | 102 | 202 | 이 교수 | + +- 학생 ID, 과목 ID, 교수 ID를 사용해 교수 이름을 결정 + +- 올바른 예 +- 학생과목 테이블 + +| 학생 ID | 과목 ID | +| ------- | ------- | +| 1 | 101 | +| 1 | 102 | + +- 과목교수 테이블 + +| 과목 ID | 교수 ID | +| ------- | ------- | +| 101 | 201 | +| 102 | 202 | + +- 교수 테이블 + +| 교수 ID | 교수 이름 | +| ------- | --------- | +| 201 | 김 교수 | +| 202 | 이 교수 | + +- 장점 + - 데이터 중복 최소화 : 저장 공간 절약할 수 있다. + - 데이터 무결성 유지 : 일관성 + 무결성 보장 + - 업데이트 이상 방지 : 데이터 수정 시 오류 가능성이 줄어든다. +- 단점 + - 성능 저하 : 조인이 자주 발생 -> 조인 성능 저하 + - 복잡성 증가 : 데이터 구조 복잡, 쿼리 작성 복잡 + +### Join이란? + +- 두 개 이상의 테이블을 결합해 하나의 결과를 생성하는 SQL 연산 +- 서로 다른 테이블에 분산된 데이터를 연결하고, 하나의 결과 세트로 만들 수 있다. + +#### INNER JOIN + +- 두 테이블 간 일치하는 데이터만 결합 +- 공통된 값이 있는 행만 결과에 포함 +- JOIN == INNER JOIN + +#### LEFT JOIN + +- 왼쪽 테이블의 모든 행을 반환하고 오른쪽 테이블과 일치하는 데이터가 있으면 그것을 포함 +- 오른쪽 테이블에 일치하는 값이 없으면 해당 컬럼에 NULL이 반환된다. + +#### RIGHT JOIN + +- 오른쪽 테이블의 모든 행을 반환하고 왼쪽 테이블과 일치하는 데이터가 있으면 그것을 포함 +- 왼쪽 테이블에 일치하는 값이 없으면 해당 컬럼에 NULL이 반환된다. + +#### FULL JOIN + +- 양쪽 테이블에서 일치하는 데이터는 결합하고 일치하지 않는 데이터는 각각 NULL로 반환 +- 왼쪽 테이블과 오른쪽 테이블의 모든 행을 반환한다. + +#### CROSS JOIN + +- 두 테이블의 모든 가능한 조합을 반환한다. +- 첫 번째 테이블의 모든 행이 두 번째 테이블의 모든 행과 결합된다. +- WHERE절을 사용하지 않는다. + +### RDBMS vs NoSQL + +#### RDBMS + +- 관계형 데이터베이스 관리 시스템 +- 데이터를 테이블 형식으로 저장한다. +- 스키마에 따라 데이터 구조를 정의한다. +- 정규화가 중요하다 -> 중복 없이 효율적으로 관리하려면 여러 테이블로 분리해 데이터 저장 +- 강력한 트랜잭션 처리와 데이터 일관성 + +#### NoSQL + +- 비관계형 데이터베이스 시스템 +- 문서, 키-값, 그래프, 컬럼 등 여러가지 형식으로 데이터를 저장할 수 있다. +- 데이터 구조를 자주 변경하거나 복잡한 관계를 저장하는 데 유리하다. +- 가용성과 확장성 중시 + +### CAP 정리(브루어 정리) + +- 데이터베이스 시스템에서 일관성, 가용성, 파티션 허용성 사이에서 동시에 세 가지를 만족시킬 수 없다 +- 데이터베이스 시스템을 설계할 때 제약을 명확히 알려준다. +- 어떤 특성을 우선시할지 결정하고 그에 따른 타협을 잘 관리할 수 있게 된다. +- 일관성 + - 모든 노드에 저장된 데이터는 동일해야 한다. +- 가용성 + - 모든 요청에 대해 응답을 제공해야 한다. +- 파티션 허용성 + - 네트워크 분할이 발생해도 시스템이 계속 동작해야 한다. + +#### 조합 + +- CA(일관성 + 가용성) + - 네트워크 파티션이 발생하지 않는 경우에만 동작한다. + - 분산 시스템에서는 파티션 허용이 중요한 요소이므로 실용적이지 않다. +- CP(일관성 + 파이션 허용성) + - 네트워크 파이션이 발생했을 때도 일관성 보장 + - 일부 노드가 응답하지 않아도 시스템은 정상 동작해야 하므로 가용성을 희생할 수 있다. + - 일부 쿼리나 요청은 실패할 수 있지만 데이터 일관성은 보장된다. +- AP(가용성 + 파티션 허용성) + - 네트워크 파티션이 발생해도 계속해서 가용성을 제공하며 일부 데이터가 최신이 아닐 수 있다. + +### 파티셔닝과 샤딩 + +- 대규모 데이터베이스 시스템에서 성능을 향상시키고 관리가 용이하도록 데이터를 나누는 방법 + +#### 파티셔닝 + +- 데이터를 여러 개의 분할된 파티션으로 나누는 기술 +- 단일 데이터베이스 내에서 데이터를 나누는 방식 -> 데이터의 논리적 분할