Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Database] A07, A08, A09 #3

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions database/A-07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

## 1. 정규화가 무엇인가요?

관계형 데이터베이스 설계에서 중복을 최소화하여 무결성을 유지하도록 하는 것입니다.

### 정규화를 하지 않을 경우, 발생할 수 있는 이상현상에 대해 설명해 주세요.

- 삽입 이상(Insertion Anomaly) : 새로운 데이터를 삽입하기 위해 불필요한 데이터도 함께 삽입해야 하는 상황입니다.
- 삭제 이상(Deletion Anomaly) : 하나의 데이터를 삭제할 때 관련된 데이터도 함께 삭제되어 정보 손실이 발생하는 상황입니다.
- 수정 이상(Update Anomaly) : 데이터의 중복으로 인해 한 데이터를 여러 곳에서 수정해야 하며, 일부만 수정될 경우 데이터의 불일치(일관성 문제)가 발생할 수 있는 상황입니다.

### 각 정규화에 대해, 그 정규화가 진행되기 전/후의 테이블의 변화에 대해 설명해 주세요.

- 1정규형 전/후
- 전: 테이블에는 중복된 레코드가 존재할 수 있고, 하나의 필드 내에 여러 값이 저장될 수 있습니다(비원자적 값). 예를 들어, 하나의 레코드에서 '취미' 필드에 ["독서", "영화감상"] 같이 여러 취미를 배열이나 문자열로 저장할 수 있습니다.
- 후: 각 필드의 값은 원자적이 되어야 합니다. 즉, 하나의 필드에는 하나의 값만을 가집니다. '취미' 정보를 저장하기 위해서는 취미마다 별도의 레코드를 추가해야 하며, 이는 테이블의 구조를 변경하여 각 취미가 별도의 레코드로 분리됩니다.

- 2정규형 전/후
- 전: non-key 속성들이 PK 와 연관되어 있다.
- 후 : 각 non-key 속성은 PK 전체에 의존해야 한다.

- 3정규형 전/후
- 전 : non-key 속성이 다른 non-key 속성에 의존한다.
- 후 : 모든 non-key 속성은 오로지 key에만 의존한다.


### 정규화가 무조건 좋은가요? 그렇지 않다면, 어떤 상황에서 역정규화를 하는게 좋은지 설명해 주세요.

DB 정규화는 테이블을 많이 나누게 하고, 테이블이 많아지면 Join 연산이 많아집니다. Join 은 성능에 큰 악영향을 미칩니다.

또한 정규화는 쓰기에 최적화되어 있습니다. 하지만 읽기가 훨씬 많은 비중을 차지합니다.

따라서 아래와 같은 상황에서 역정규화를 하는 것이 좋습니다.
- **조회 성능 향상** : 데이터베이스에서 조회(쿼리) 작업이 매우 빈번하고, 데이터의 추가, 삭제, 수정(갱신) 작업은 상대적으로 드문 경우입니다. 자주 함께 조회되는 데이터를 하나의 테이블로 합치거나, 계산된 값을 저장하는 추가 필드(예: 집계 정보)를 도입하여 쿼리의 복잡성을 줄이고 조회 성능을 향상시킬 수 있습니다.

- **갱신 작업 최소화** : 데이터 갱신 작업이 비교적 적고, 특히 시스템의 성능이 중요한 역할을 하는 애플리케이션에서, 정규화된 구조에서는 하나의 데이터를 업데이트하기 위해 여러 테이블을 수정해야 할 수 있습니다. 이때 역정규화를 적용하여 중복 데이터를 저장함으로써 갱신 작업을 줄이고, 이로 인한 시스템의 성능을 향상시킬 수 있습니다.


## 참고
- [정규화(Normalization) 쉽게 이해하기](https://mangkyu.tistory.com/110)
- [[데이터베이스] 정규화의 의미 - 1NF, 2NF, 3NF, 4NF, 5NF](https://ddoddii.github.io/post/cs/database/normalization/)
- [DB 정규화를 하지 않는 이유](https://coolspeed.wordpress.com/2017/04/15/why_not_db_normalization/)
11 changes: 11 additions & 0 deletions database/A-08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## 8. View가 무엇이고, 언제 사용할 수 있나요?

View 는 사용자에게 접근이 허용된 자료만을 제한적으로 보여주기 위해 하나 이상의 기본 테이블에서 유도된, 이름을 가지는 **가상 테이블**입니다. 뷰는 저장장치 내에 물리적으로 존재하지는 않습니다. 뷰를 통해서만 데이터에 접근하게 하면 뷰에 나타나지 않는 데이터를 보호할 수 있습니다. 뷰를 사용하면 기본 테이블 구조가 변경되어도 응용 프로그램은 계속 동일한 뷰를 사용할 수 있어서, 데이터 독립성을 제공합니다.

### 그렇다면, View의 값을 수정해도 실제 테이블에는 반영되지 않나요?

View 의 종류에 따라 다릅니다. Updatable View 에서는 데이터를 수정,삽입,삭제하면 기본 테이블에도 반영됩니다. Read-Only View 에서는 데이터를 수정할 수 없습니다.


## 참고
- [[DB기초] 뷰(View)란 무엇인가? + 간단한 예제](https://coding-factory.tistory.com/224)
115 changes: 115 additions & 0 deletions database/A-09.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
## 9. DB Join이 무엇인지 설명하고, 각각의 종류에 대해 설명해 주세요.

DB Join 은 두 개 이상의 테이블에서 관련된 데이터를 결합하여 의미 있는 정보를 얻기 위해 사용되는 연산입니다. 조인은 테이블 간의 공통 열(일반적으로 기본 키와 외래 키)을 기반으로 수행됩니다.

Join 의 종류는 다음과 같습니다.
- Inner Join
- 두 테이블에서 조인 조건을 만족하는 행만 반환합니다.
- LEFT OUTER JOIN
- 왼쪽 테이블의 모든 행을 반환하고, 오른쪽 테이블에서 조인 조건을 만족하는 행을 함께 반환합니다.
- RIGHT OUTER JOIN
- 오른쪽 테이블의 모든 행을 반환하고, 왼쪽 테이블에서 조인 조건을 만족하는 행을 함께 반환합니다.
- FULL OUTER JOIN
- 왼쪽 및 오른쪽 테이블의 모든 행을 반환합니다.
- CROSS JOIN
- 테이블의 모든 행을 결합하여 가능한 모든 조합을 반환합니다.
- SELF JOIN
- 하나의 테이블 내에서 자기 자신과 조인하는 것을 의미합니다.

### 사실, JOIN은 상당한 시간이 걸릴 수 있기에 내부적으로 다양한 구현 방식을 사용하고 있습니다. 그 예시에 대해 설명해 주세요.

주요한 네 가지 조인 알고리즘으로는 **Nested Loop Join, Hash Join, 그리고 Sort Merge Join, Index Join**이 있습니다.

1. Nested Loop Join:

- Nested Loop Join은 가장 간단한 조인 알고리즘 중 하나로, 바깥쪽 루프(Outer Loop)와 안쪽 루프(Inner Loop)로 두 테이블을 순차적으로 순회하면서 조인합니다.
- 바깥쪽 루프는 기준 테이블을 선택하고, 안쪽 루프는 조인 조건에 해당하는 테이블을 선택합니다.
- 조인 조건에 해당하는 데이터를 찾으면, 바깥쪽 루프의 다음 행으로 넘어가며, 안쪽 루프는 처음부터 다시 시작합니다
- 데이터 양이 적을 때는 성능이 좋지만, 데이터 양이 많을 경우 비효율적일 수 있습니다.


2. Hash Join:

- 해시 함수를 사용하여 조인 키를 기반으로 테이블을 해시 버킷에 분할합니다.
- 두 테이블의 해시 버킷을 비교하여 조인 조건을 만족하는 행을 찾습니다.
- 대용량 데이터 세트에 적합하며, 일반적으로 Nested Loop Join보다 빠릅니다.


3. Sort Merge Join:

- 조인 키를 기준으로 두 테이블을 정렬합니다.
- 정렬된 테이블을 병합하면서 조인 조건을 만족하는 행을 찾습니다.
- 데이터가 이미 정렬되어 있거나, 조인 결과를 정렬해야 하는 경우에 효율적입니다.

4. Index Join (인덱스 조인):

- 조인 키에 대한 인덱스를 사용하여 조인을 수행합니다.
- 한 테이블에서 인덱스를 사용하여 조인 키를 빠르게 찾고, 다른 테이블에서 해당 키와 일치하는 행을 검색합니다.
- 인덱스가 있는 열을 조인할 때 효율적입니다.

### 그렇다면 입력한 쿼리에서 어떤 구현 방식을 사용하는지는 어떻게 알 수 있나요?

EXPLAIN (또는 EXPLAIN PLAN) 명령을 사용할 수 있습니다. 대부분의 DBMS는 EXPLAIN 명령을 제공하여 쿼리 실행 계획을 확인할 수 있습니다. 쿼리 앞에 EXPLAIN을 붙여 실행하면, 쿼리 옵티마이저가 선택한 실행 계획을 볼 수 있습니다. 실행 계획에는 사용된 조인 알고리즘, 조인 순서, 인덱스 사용 여부 등의 정보가 포함됩니다.

### 앞 질문들을 통해 인덱스의 중요성을 알 수 있었는데, 그렇다면 JOIN의 성능도 인덱스의 유무의 영향을 받나요?

네, 조인의 성능은 인덱스의 유무에 큰 영향을 받습니다. 적절한 인덱스를 사용하면 조인 연산의 속도를 크게 향상시킬 수 있습니다. 인덱스가 조인 성능에 미치는 영향은 다음과 같습니다:

1. 인덱스를 사용한 조인 (Index Join):
- 조인 조건에 사용되는 열에 인덱스가 있는 경우, DBMS는 인덱스를 사용하여 빠르게 일치하는 행을 찾을 수 있습니다.
- 인덱스를 사용하면 테이블 전체를 스캔하지 않고도 필요한 데이터에 접근할 수 있어 조인 성능이 향상됩니다.

2. 인덱스 없이 수행되는 조인 (Non-Index Join):
- 조인 조건에 사용되는 열에 인덱스가 없는 경우, DBMS는 테이블 전체를 스캔해야 합니다.
- 이는 조인 연산의 속도를 크게 저하시키며, 특히 대용량 테이블에서는 성능 문제가 두드러집니다.

3. 인덱스 선택성 (Index Selectivity):
- 인덱스의 선택성이 높을수록 조인 성능이 향상됩니다.
- 선택성이 높은 인덱스는 중복 값이 적고 고유한 값이 많은 인덱스를 의미합니다.
- 선택성이 높은 인덱스를 사용하면 조인 조건을 만족하는 행을 빠르게 찾을 수 있습니다.

4. 다중 열 인덱스 (Multi-Column Index):
- 조인 조건에 여러 열이 사용되는 경우, 다중 열 인덱스를 생성하면 조인 성능을 향상시킬 수 있습니다.
- 다중 열 인덱스는 조인 조건에 사용되는 열의 순서와 일치하도록 생성되어야 합니다.

5. 클러스터형 인덱스 (Clustered Index):
- 클러스터형 인덱스는 테이블 데이터를 물리적으로 정렬하여 저장합니다.
- 조인 조건에 클러스터형 인덱스를 사용하면, 인덱스 스캔과 데이터 검색이 함께 이루어지므로 성능이 향상됩니다.

따라서, 조인 성능을 최적화하려면 적절한 인덱스를 생성하고 사용해야 합니다. 조인 조건에 사용되는 열에 선택성이 높은 인덱스를 생성하고, 필요한 경우 다중 열 인덱스를 사용하는 것이 좋습니다. 인덱스를 효과적으로 활용하면 조인 연산의 속도를 크게 향상시킬 수 있습니다.


### 3중 조인 부터는 동작 방식이 약간 바뀝니다. 어떻게 동작하는지, 그리고 그 방식이 성능에 어떠한 영향을 주는지 설명해 주세요.

3개 이상의 테이블을 조인할 때, 조인 순서와 실행 계획이 성능에 큰 영향을 미칩니다. DBMS의 쿼리 옵티마이저는 통계 정보와 규칙 기반 휴리스틱을 사용하여 최적의 조인 순서를 결정합니다. 다중 테이블 조인의 동작 방식과 성능에 미치는 영향은 다음과 같습니다:

1. 조인 순서 (Join Order):
- 쿼리 옵티마이저는 다양한 조인 순서를 평가하여 가장 효율적인 실행 계획을 선택합니다.
- 조인 순서는 테이블의 크기, 조인 조건의 선택성, 인덱스 사용 가능성 등을 고려하여 결정됩니다.
- 최적의 조인 순서를 선택하면 불필요한 중간 결과를 최소화하고 조인 성능을 향상시킬 수 있습니다.

2. 중첩 루프 조인 (Nested Loop Join):
- 다중 테이블 조인에서 중첩 루프 조인이 사용되는 경우, 조인 순서에 따라 성능이 크게 달라질 수 있습니다.
- 작은 테이블을 먼저 조인하고, 큰 테이블을 나중에 조인하는 것이 일반적으로 더 효율적입니다.
- 중첩 루프 조인은 작은 테이블에 인덱스가 있을 때 효과적입니다.

3. 해시 조인 (Hash Join):
- 다중 테이블 조인에서 해시 조인이 사용되는 경우, 큰 테이블을 먼저 해시 테이블로 빌드하고 작은 테이블을 프로브하는 것이 일반적입니다.
- 해시 조인은 큰 테이블과 작은 테이블 간의 조인에 효과적이며, 인덱스가 없는 경우에도 높은 성능을 제공합니다.

4. 조인 필터 조건 (Join Filter Condition):
- 다중 테이블 조인에서 추가적인 필터 조건을 사용하면 중간 결과 집합의 크기를 줄일 수 있습니다.
- 필터 조건을 가능한 한 빨리 적용하여 불필요한 데이터 처리를 최소화할 수 있습니다.

5. 조인 방향 (Join Direction):
- 조인 방향은 어떤 테이블을 먼저 액세스하고 어떤 테이블을 나중에 액세스할지 결정합니다.
- 일반적으로 작은 테이블에서 큰 테이블 방향으로 조인하는 것이 효율적입니다.
- 조인 방향은 인덱스 사용 가능성과 조인 조건의 선택성에 따라 결정됩니다.


## 참고
- [DB Join 정리(INNER/LEFT/RIGHT/OUTER)](https://pearlluck.tistory.com/46)
- [관계형 데이터베이스(RDBMS) 조인 알고리즘 종류: Nested Loop Join, Hash Join, Sort Merge Join](https://bestwizard.tistory.com/583)
- [[SQL] 성능 관점에서 보는 결합(Join)](https://schatz37.tistory.com/2)
- [[MYSQL] 📚 테이블 조인(JOIN) - 그림으로 알기 쉽게 정리](https://inpa.tistory.com/entry/MYSQL-%F0%9F%93%9A-JOIN-%EC%A1%B0%EC%9D%B8-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EA%B8%B0%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC)
- [[DB] 데이터베이스 NESTED LOOPS JOIN (중첩 루프 조인)에 대하여](https://coding-factory.tistory.com/756)