만능은 없다. TradeOff는 있다.
읽기 성능이 좋으면 쓰기성능이 구리고, 쓰기성능이 좋으면 읽기성능에 구려진다.
정규화
쓰기성능을 높임으로써 데이터 중복을 줄이고 일관성을 높인다.
반정규화
읽기성능을 높임으로써 일부 중복을 허용한다.
트랜잭션 격리 수준
Uncommitted Read - 커밋되지 않은 읽기
- 다른 트랜잭션에서 커밋되지 않은 데이터에도 접근하게 할 수 있는 격리수준
- DirtyRead: 커밋되지 않은 트랜잭션에 접근해서 아직 정상반영되지 않은 데이터를 읽는 현상 (해당 데이터는 롤백되어 없어질 수도 있다)
Committed Read - 커밋된 읽기
- 다른 트랜잭션에서 커밋된 데이터에만 접근할 수 있게 하는 격리수준
- Non-Repeatable Read: 하나의 트랜잭션에서 동일한 SELECT 쿼리문을 실행했을 때 커밋전의 데이터와 커밋후의 데이터가 읽히면서 다른결과가 생기는 현상
Repeatable Read - 반복가능한 읽기
커밋된 데이터만 읽을 수 있으며, 자신보다 빨리 수행된 트랜잭션에서 커밋한 데이터만 읽을 수 있는 격리 수준
MVCC를 통해 Undo 로그를 기반으로 동일한 데이터가 조회되도록 보장하여 Non-Repeatabe Read 문제를 해결한다.
ORACLE 와 같이 Repeatable Read를 지원하지 않는 데이터베이스에서는 배타락을 이용해서 문제를 해결한다.
Phantom Read: 하나의 트랜잭션내에서 동일한 SELECT 쿼리의 결과 레코드수가 달라지는 현상
- InnoDB 엔진에 의해 SELECT ~ FOR UPDATE 구문을 지원해주며, Next Key Lock 형태의 배타락을 지원해주기 때문에 MYSQL 에서는 Phantom Read가 발생하지 않는다
Serializable
- 모든 트랜잭션을 순차적으로 실행시켜주는 격리 수준
- 트랜잭션이 서로 끼어들 수 있는 상황이 없으므로 데이터의 부정합 문제는 발생하지 않는다.
- 트랜잭션이 동기적으로 처리되면서 처리속도 저하가 발생한다
- S-LOCK으로 조회후 Update하려고 할때 대기상태가 되므로 Dead Lock 문제가 발생한다
InnoDB의 격리수준
- 기본값은 Repeatable Read 이다.
- Mysql InnoDB에서는 MVCC(Multi-Version-Concurrency Control)을 사용해서 Phantom Read도 방지할 수 있다.
격리수준 설정방법
- 전역 설정
| |
- 세션설정
| |
- 트랜잭션 시작시 설정하기
MVCC(Multi-Version-Concurrency Control)
인덱스(Index)

- 위의 예시처럼 책의 목차를 보면, 각 목차별로 페이지를 기재해준다.
- 검색속도 향상을 위해서 데이터(data row)를 식별가능하도록 저장하는 객체이다.
- 검색속도 향상으로 데이터베이스 부하 감소를 목적으로 한다.
인덱스 개념
- 특정 컬럼으로 인덱스를 설정하면, 해당 컬럼의 값을 정렬하여 데이터를 적재해두어 해당 컬럼의 조회 성능을 향상시킨다.
- 1~100까지의 수를 랜덤하게 펼쳐두고 30보다 작은 값을 찾는다.
- 1~100까지의 수를 오름차순으로 정렬하고 30보다 작은 값을 찾는다.
- 인덱스는 조회성능을 높일 수 있지만 아래 사항을 고려하여 설계해야한다.
- 한번에 찾을 수 있는 값인가? - 데이터 중복이 적은 컬럼
- 인덱스 재정렬을 최소화할 수 있는가? - 데이터 삽입, 수정이 적은 컬럼.
- 인덱스의 목적은 검색이다 - 조회에 자주사용되는 컬럼
- 너무 많지 않은 인덱스 - 인덱스도 별도의 공간을 차지.
- 인덱스도 공간을 차지하기 때문에 너무 많이 있어도 문제가 생긴다.
- 인덱스 조정때문에 쓰기연산인 데이터 삽입/수정/삭제 연산 성능이 하락될 수 있다.
그럼 인덱스는 언제 필요할까?
- 데이터가 너무 많아서 조건에 부합하는 결과데이터를 찾는데 오래걸릴 경우
단일 인덱스
- 1개 컬럼으로 구성된 인덱스
복합 인덱스
- 2개이상의 컬럼으로 구성된 인덱스
- 카디널리티가 높은 컬럼순으로 구성해야 검색속도를 높일 수 있다.
- 인덱스의 컬럼 순서와 조건 조회 순서가 일치하지 않으면 인덱스를 이용하지 않는다.
Covering 인덱스
- 특정 쿼리를 충족시키는데 필요한 모든 데이터를 포함하는 인덱스
- 모든컬럼의 조회대상, 조회 조건에 포함된다면 데이터를 찾기위해서 Row에 접근할 필요가 없으므로, 인덱스 스캔만 발생하므로 높은 조회 성능을 가진다.
카디널리티(Cardinality)
- 정의: 테이블의 열(column)이 가지는 고유한 값의 개수를 의미한다.
| ID | GENDER |
|---|---|
| 1 | M |
| 2 | F |
| 3 | F |
| 4 | F |
| 5 | M |
- gender 컬럼의 카디널리티개수: 2개 (M/F)
- ID 컬럼의 카디널리티개수: 5개 (모두 고유하다)
종류
- 높은 카디널리티: 고유값이 많은 컬럼
- 예) 주민등록번호, 이메일, 고유 PK 식별자 ID
- 중간 카디널리티: 값이 적당히 중복되는 컬럼
- 예) 우편번호, 도시이름, 이름
- 낮은 카디널리티: 값이 거의 중복되는 컬럼
- 예) 성별(M/F), 국가(대한민국)
- 높은 카디널리티: 고유값이 많은 컬럼
카디널리티와 인덱스의 연관관계
- 카디널리티가 높을수록 인덱스 성능이 좋다. 왜냐하면 인덱스를 통해서 많은 데이터를 빠르게 걸러낼 수 있기 때문이다.
- 카디널리티가 낮을수록 컬럼에 인덱스를 걸게되면 인덱스보다는 테이블 풀스캔이 더 효율적일 수 있다.
관계형 모델에서의 카디널리티(엔티티 관계)
- 1:1
- 1:N
- N:M
Sync Schedule Strategy
통계 데이터를 활용하는 방법이다.
실시간성과 정합성의 Trade-Off 를 극복하기위해서 데이터베이스 I/O를 줄이고 언젠간 정합성이 맞아 떨어지는 환경을 구성하는 전략이다.
자주 삽입/수정하는 데이터에 대해서 인덱스를 적용하게되면 인덱스의 재조정으로 인해서 성능이 하락될 수 있다. 인덱스도 공간을 차지할 수 있으므로, 인덱스를 통해서 읽어야할 데이터레코드가 전체데이터베이스에서 20~25% 넘게 차지한다면 인덱스로 읽기보다는 테이블의 데이터를 직접 읽는 것이 더 효율적이다.