ERD
Entity Relation Diagram
지금 만들고 있는 Photoverse의 ERD이다.
인텔리제이 Diagram 생성으로 만든거라 테이블간 연관관계가 화살표로 되어 있는데 보통은 간선에 기호를 붙여서 나타내는 게 일반적이다.
선이 실선이 아니고 점선인 경우에는 자식 테이블이 부모 테이블의 기본키를 기본키로 사용하지 않는 경우에 대한 표현법이다.
좀 더 쉬운 예시를 보면,
사원은 0 ~ n 명의 고객을 가질 수 있다.
고객은 0 ~ n 개의 주문을 넣을 수 있다.
주문은 1 ~ n 개의 상품이 들어갈 수 있다.
는 뜻을 나타내고 있다.
ERD를 통해 테이블 간의 관계를 쉽게 표현하고 이해할 수 있다.
Join
Join?
- 조인은 두 개 이상의 테이블을 연결하여 데이터를 탐색하는 방법이다. (대부분의 SQL에서는 JOIN을 사용, MongoDB의 경우엔 lookup 이라는 키워드 사용)
Inner Join
- 두 테이블에서 일치하는 데이터만 반환. (교집합)
- A, B 테이블을 Inner Join 하면 A, B 모두에 존재하는 데이터만 쿼리된다.
Outer Join
- 외부 조인은 Left Outer Join, Right Outer Join, Full Outer Join의 3가지 케이스가 있다.
Left Outer Join
- 첫 번째 테이블(왼쪽)과 두 번째 테이블(오른쪽)의 일치하는 레코드를 반환한다.
- 오른쪽 테이블에 일치하는 레코드가 없다면 왼쪽 테이블 레코드는 그대로 출력하고 오른쪽의 레코드는 NULL로 출력한다.
Right Outer Join
- 레프트 조인의 반대이다.
- 왼쪽 테이블에 일치하는 레코드가 없는 경우에는 NULL로 출력한다.
Full Outer Join
- 두 테이블의 모든 레코드를 반환한다.
- 한 테이블에만 존재하는 경우에는 나머지 테이블의 영역을 NULL로 출력한다.
Cross Join
- 두 개 이상의 테이블에서 가능한 모든 행의 조합을 생성하는 조인방법
- 두 테이블 간에 어떠한 조인 조건이 없을 때 사용. 두 테이블의 모든 행 간에 Cartesian product를 형성한다.
- 쓸 일이 잘 없긴 한데 테스트용으로 사용하거나 POC를 할 때 간혹 사용한다고 한다.
Natual Join
- 두 테이블 간에 동일한 이름을 가진 열이 있는 경우 자동으로 찾아서 Inner Join을 수행한다.
Transaction
트랜잭션
- 데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위
커밋
- 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어.
- 트랜잭션 단위로 수행되며 변경된 내용이 모두 영구적으로 저장됨.
롤백
- 트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 돌리는 일 (Ctrl Z)
트랜잭션 전파
- 트랜잭션을 수행할 때 커넥션 단위로 수행하기 때문에 커넥션 객체를 넘겨서 수행해야 하는데 이를 넘겨서 수행하지 않고 여러 트랜잭션 관련 메서드의 호출을 하나의 트랜잭셩에 묶이도록 하는 것.
트랜잭션의 특성
ACID
- Atomicity
- 원자성: 트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았거나를 보장하는 특징
- Consistency
- 일관성: 허용된 방식으로만 데이터를 변경해야 하는 것을 의미
- Isolation
- 격리성: 트랜잭션 수행 시 서로 끼어들지 못하도록 하는 것을 의미
- Durability
- 지속성: 성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다는 의미.
격리성
DB를 다루다 보면 격리성에 대한 이야기를 하게 되고 질문도 많이 나온다.
격리성에는 정도가 있다. 격리성이 높을수록 동시성이 낮아지고 성능도 낮아진다.
격리수준
- SERIALIZABLE
- 커밋 완료된 데이터에 대해서만 조회할 수 있다.
- 트랜잭션을 순차적으로 진행시킨다.
- 여러 트랜잭션이 동시에 같은 행에 접근할 수 없다.
- REPEATABLE_READ
- 커밋 완료된 데이터에 대해서만 조회할 수 있다.
- 반복해서 행을 조회하더라도 똑같은 결과를 보장한다.
- 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주미나 새로운 행을 추가하는 것은 막지 않는다.
- 따라서 팬텀 리드는 일어날 수 있는 격리수준이다.
- MySql 8.0의 기본값이다.
- READ_COMMITED
- 커밋 완료된 데이터에 대해서만 조회할 수 있다.
- 커밋이 되지 않은 정보는 읽지 못한다.
- 가장 많이 사용되는 수준으로 PostgreSQL, SQL Server, 오라클의 기본값이다.
- READ_UNCOMMITED
- 가장 낮은 격리 수준이기 떄문에 가장 빠르다.
- 다른 트랜잭션이 커밋하지 않은 정보를 읽을 수 있다.
- 팬텀리드, 논리피터블 리드, 더티 리드가 모두 발생할 수 있다.
격리수준에 따른 현상
팬텀리드 (Phantom Reads)
- 한 트랜잭션 내에서 동일한 쿼리를 2번 이상 날렸을 때 조회 결과가 다른 현상.
반복 가능하지 않은 조회 (Nonrepeatable Reads)
- 한 트랜잭션 내의 같은 행에 두 번 이상 조회를 했을 때, 그 두 조회의 값이 다른 현상.
더티 리드 (Dirty Reads)
- 하나의 트랜잭션이 다른 트랜잭션의 아직 커밋되지 않은 데이터를 읽는 현상.
인덱스
인덱스란?
- 데이터베이스 인덱스는 데이터 접근 속도를 향상시키기 위해 사용되는 데이터 구조이다.
B-Tree
- 보통 인덱스로 많이 쓰이는 구조의 이름.
- 이진 검색 트리를 일반화한 자료구조.
- 2개 이상의 자식을 가진 노드를 허용하고 탐색에 평균 O(logN)의 시간이 걸린다.
- 대수확장성이라는 특징을 가지고 있어서 더 빠른 속도로 더 많은 양의 데이터를 검색할 수 있다.
대수확장성
- 대수확장성은 트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것을 뜻한다.
인덱스 성능 최적화
- 인덱스는 두 번 탐색하도록 강요한다. 인덱스 리스트 -> 컬렉션 순으로 탐색하기 때문이고 읽기에 따른 비용이 수반된다.
- 이 때문에 사용되지 않거나 중복되는 인덱스, 불필요한 인덱스는 제거해야 한다.
- 인덱스는 컬렉션이 수정되면 같이 수정되야 한다. 이 또한 비용의 발생이다.
- 복합 인덱스를 설정할 때는 인덱스 생성 순서도 중요하다.
- ==, equal 등의 쿼리가 있다면 제일 먼저 인덱스로 설정한다.
- 정렬에 쓰는 필드가 있다면 그 다음 인덱스로 설정한다.
- 다중 값을 출력해야 하는 필드(<, >, between 등)가 있다면 그 다음 인덱스로 설정한다.
- 카디널리티(값의 유니크 정도)가 높은 순서대로 설정한다.