mojo's Blog

데이터베이스 정리 본문

Computer Science/데이터베이스

데이터베이스 정리

_mojo_ 2022. 9. 3. 21:50

 

데이터베이스의 기본

 

데이터베이스는 일정한 규칙, 혹은 규약을 통해 구조화되어 저장되는 데이터 모음이다.

데이터베이스를 제어, 관리하는 통합 시스템을 DBMS 라고 하며, 데이터베이스 안에 있는 데이터들을

특정 DBMS 마다 정의된 쿼리 언어를 통해 삽입, 삭제, 수정, 조회 등을 수행할 수 있다.

 

 

데이터베이스 위에 DBMS, DBMS 위에 응용 프로그램이 있으며 이러한 구조로 데이터를 주고 받는다.

DBMS 는 예로 MySQL 이 있으며 응용 프로그램에 속하는 Node.js, php 에서 해당 데이터베이스 안에 있는

데이터를 가져와서 해당 데이터 관련 로직을 구축할 수 있다.

 

 

※ 엔티티

 

엔티티는 사람, 장소, 물건, 사건, 개념 등 여러 개의 속성을 지닌 명사를 의미한다.

예를 들어 회원은 이름, 아이디, 주소, 전화번호의 속성을 가진다.

 

 

※ 릴레이션

 

릴레이션은 데이터베이스에서 정보를 구분하여 저장하는 기본 단위이다.

엔티티에 관한 데이터를 데이터베이스는 릴레이션 하나에 담아서 관리한다.

- 관계형 데이터베이스 : 릴레이션을 테이블이라 부르며 구조는 레코드 - 테이블 - 데이터베이스 이다.

- NoSQL 데이터베이스 : 릴레이션을 컬렉션이라 부르며 구조는 도큐먼트 - 컬렉션 - 데이터베이스 이다.

 

 

※ 속성

 

속성은 릴레이션에서 관리하는 구체적이며 고유한 이름을 갖는 정보이다.

서비스의 요구 사항을 기반으로 관리해야 할 필요가 있는 속성들만 엔티티의 속성이 된다.

 

 

※ 도메인

 

도메인이란 릴레이션에 포함된 각각의 속성들이 가질 수 있는 값의 집합을 말한다.

예를 들어 성별이라는 속성이 있을 때 이 속성이 가질 수 있는 값은 {남, 여} 집합이다.

 

 

※ 필드와 레코드

 

 

회원이란 엔티티는 member 테이블로 속성인 이름, 전화번호, 아이디 등의 필드를 가진다.

테이블에 쌓이는 행(row) 단위의 데이터를 레코드라고 하며 레코드는 튜블이라고 부른다.

 

 

※ 필드 타입

 

- 날짜 타입 : DATE, DATETIME, TIMESTAMP 등이 있다.

 

  • DATE : 날짜 부분은 있고 시간 부분은 없는 값으로 3 바이트 용량을 차지 (1000-01-01 ~ 9999-12-31)
  • DATETIME : 날짜, 시간 모두를 포함하는 값으로 8 바이트 용량 차지 (1000-01-01 00:00:00 ~ 9999-12-31 23:59:59)
  • TIMEMSTAMP : 날짜, 시간 모두를 포함하는 값으로 4 바이트 용량 차지 (1970-01-01 00:00:01 ~ 2038-01-19 03:14:07)

- 문자 타입 : CHAR, VARCHAR, TEXT, BLOB, ENUM, SET 등이 있다.

 

  • CHAR : 길이가 고정되며 길이는 0 에서 255 사이의 값을 가짐
  • VARCHAR : 가변 길이 문자열로 길이는 0 에서 65,535 사이의 값을 지정 가능
  • TEXT : 큰 문자열 저장에 쓰임 (ex : 게시판 본문 저장)
  • BLOB : 이미지, 동영상 등 큰 데이터 저장에 쓰임
  • ENUM : ENUM 형태로 쓰이며, 하나만 선택하는 단일 선택만 가능 (ENUM 리스트에 없는 값 삽입시 빈 문자열)
  • SET : ENUM 과 비슷하지만 여러 개의 데이터 선택이 가능하고 비트 단위의 연산을 할 수 있으며 최대 64 개의 요소를 삽입 가능

 

※ 관계

 

- 1:1 관계

예를 들어 유저당 이메일은 한 개씩 존재하며 이 경우를 1:1 관계라 부른다.

 

 

- 1:N 관계

예를 들어 한 유저당 여러 개의 상품을 장바구니에 넣을 수 있으며 이 경우를 1:N 관계라 부른다.

이때 장바구니에 하나도 넣지 않는 0개의 경우도 있으므로 0도 포함되는 화살표를 통해 표현할 수 있다.

 

 

- N:M 관계

예를 들어 학생과 강의의 관계로 학생은 강의를 여러개 선택 가능하고 강의도 여러 명의 학생을

포함할 수 있는데 이 경우를 N:M 관계라 부른다.

이 경우에 N:M 은 테이블 두 개를 직접적으로 연결해서 구축하지는 않고 1:N, 1:M 이라는 관계를

갖는 테이블 두 개로 나눠서 설계한다.

 

 

 키

 

테이블 간의 관계를 좀 더 명확하게 하고 테이블 자체의 인덱스를 위해 설정된 장치로

기본키, 외래키, 후보키, 슈퍼키, 대체키가 있다.

 

 

슈퍼키는 유일성이 있고 그 안에 포함된 후보키는 최소성까지 갖춘 키이다.

후보키 중에 기본키로 선택되지 못한 키는 대체키가 된다.

- 유일성 : 중복되는 값이 없는 것

- 최소성 : 필드를 조합하지 않고 최소 필드만 써서 키를 형성할 수 있는 것

 

 

※ 기본키

 

기본키는 PK(Primary Key) 로 유일성과 최소성을 만족하는 키이다.

예를 들어 아이디와 이름을 묶은 복합키를 기본키로 설정이 가능하다. 

그러나, 유일성을 만족하지만 최소성을 만족하지 않게 된다.

기본키는 자연키 또는 인조키 중에 고르게 된다.

 

 

※ 자연키

 

중복된 값들을 제외하며 중복되지 않는 것을 자연스럽게 뽑다가 나오는 키를 자연키라고 한다.

예를 들어 유저 테이블에서 주민등록번호, 이름, 성별 등의 속성이 존재한다.

이 중 이름, 성별 등은 중복된 값이 들어올 수 있으므로 부적절하고 남는 것은 주민등록번호이다.

 

 

※ 인조키

 

인위적으로 고유 식별자를 만드는 것을 의미한다.

오라클은 sequence, MySQL 은 auto increment 등으로 설정한다. (0, 1, 2, ... )

보통 기본키는 인조키로 설정한다.

 

 

※ 외래키

 

외래키는 FK(Foreign Key) 라고 하며, 다른 테이블의 기본키를 그대로 참조하는 값으로 개체와의

관계를 식별하는데 사용된다.

외래키는 중복되어도 괜찮다.

 

 

- 후보키 : 기본키가 될 수 있는 후보들로 유일성, 최소성을 동시에 만족하는 키이다.

- 대체키 : 후보키가 두 개 이상일 경우 어느 하나를 기본키로 지정하고 남은 후보키들을 말한다.

- 슈퍼키 : 각 레코드들을 유일하게 식별할 수 있는 유일성을 갖춘 키이다.

 

 

ERD, 정규화 과정

 

ERD 는 데이터베이스를 구축할 때 가장 기초적인 뼈대 역할을 하며, 릴레이션 간의 관계들을 정의한 것이다.

ERD 는 시스템의 요구 사항을 기반으로 작성되며 이 ERD 를 기반으로 데이터베이스를 구축한다.

데이터베이스를 구축한 이후에도 디버깅 또는 비즈니스 프로세스 재설계가 필요한 경우에 설계도 역할을 담당한다.

하지만 ERD 는 관계형 구조로 표현할 수 있는 데이터를 구성하는데 유용할 수 있지만,

비정형 데이터를 충분히 표현할 수 없다는 단점이 존재한다.

 

- 비정형 데이터 : 비구조화 데이터로 미리 정의된 데이터 모델이 없거나 미리 정의된 방식으로 정리되지 않은 정보

 

 

※ 정규화 과정

 

정규화 과정은 릴레이션 간의 잘못된 종속 관계로 인해 데이터베이스 이상 현상이 일어나서 

이를 해결하거나, 저장 공간을 효율적으로 사용하기 위해 릴레이션을 여러 개로 분리하는 과정이다.

 

- 이상 현상 : 예를 들어 회원이 한 개의 등급을 가져야 하는데 여러 개의 등급을 갖는 경우거나 삭제할 때

   필요한 데이터가 같이 삭제되고, 삽입시 특정 필드 값에 NULL 이 되면 안되서 삽입이 어려운 현상

 

정규화 과정은 정규화 원칙을 기반으로 정규형을 만들어가는 과정으로 정규화된 정도는 정규형(NF)으로 표현한다.

기본 정규형으로 제1정규형, 제2정규형, 제3정규형, 보이스/코드 정규형이 있다.

정규형 원칙은 자료의 중복성을 최소화하고 독립적인 관계는 별개의 릴레이션으로 표현해야 하며,

각각의 릴레이션은 독립적인 표현이 가능해야 하는 것을 말한다.

 

① 제1정규형

릴레이션의 모든 도메인은 더 이상 분해할 수 없는 원자값으로만 구성해야 한다.

릴레이션의 속성 값 중에서 한 개의 기본키에 대해 두 개 이상의 값을 가지는 반복 집합이 있으면 안된다.

 

② 제2정규형

릴레이션이 제1정규형이며 부분 함수의 종속성을 제거한 형태이다.

부분 함수의 종속성 제거란 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속적인 것을 말한다.

 

③ 제3정규형

제2정규형이고 기본키가 아닌 모든 속성이 이행적 함수 종속을 만족하지 않는 상태를 말한다.

이행적 함수 종속이란 A -> B, B -> C 가 존재하면 A -> C 가 성립하는 것으로 집합 C 가 집합 A 에 이행적으로

함수 종속이 되었다고 한다.

 

④ 보이스/코드 정규형

제3정규형이고 결정자가 후보키가 아닌 함수 종속 관계를 제거하여 릴레이션의 함수 종속 관계에서

모든 결정자가 후보키인 상태를 말한다.

결정자란 함수 종속 관계에서 특정 종속자를 결정하는 요소로 "X -> Y" 일 때 X 는 결정자, Y 는 종속자이다.

 

예를 들어 각 수강명에 대해 한 학생은 오직 한 강사의 강의만 수강하고,

각 강사는 한 수강명만 담당하며 한 수강명은 여러 강사가 담당할 수 있다고 해보자.

 

 

위 릴레이션은 {학번, 수강명} 또는 {학번, 강사} 가 후보키가 되며, "양양" 이라는 강사가"C" 라는 수강명을

담당할 때 이를 삽입할 때 학생은 없으므로 NULL 이 되는 문제가 발생한다.

즉, 강사 속성이 결정자이지만 후보키가 아니므로 강사 속성을 분리해야 한다.

 

 

테이블을 나누게 되면 삽입 이상이 사라지게 된다.

참고로 정규화 과정을 거쳐 테이블을 나눈다고 해도 성능이 항상 좋아지는 것은 아니다.

테이블을 나누게 되면 조인을 할 때 느려질 수 있기 때문에 서비스에 따라 정규화 또는 비정규화 과정을

진행해야 한다.

 

데이터베이스 정규화 설명이 잘 되어있다! 참조해야 겠다.

https://rebro.kr/160

 

[DB] 8. 정규형 (1NF, 2NF, 3NF, BCNF)

[목차] 1. 제1 정규형 2. 제2 정규형 3. 제3 정규형 4. BCNF 정규형이란 정규화된 결과를 말하며, 제1 정규형, 제2 정규형, 제3 정규형, BCNF, 제4 정규형, 제5 정규형이 있다. 실무적으로 제4, 제5 정규형은

rebro.kr

 

 

트랜잭션과 무결성

 

※ 트랜잭션

 

트랜잭션은 데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위를 말하며,

데이터베이스에 접근하는 방법은 쿼리이므로, 즉 여러 개의 쿼리들을 하나로 묶는 단위를 말한다.

특징으로 원자성, 일관성, 독립성, 지속성 4 가지가 있으며 이를 한꺼번에 ACID 특징이라고 한다.

 

 

※ 원자성 (Atomic)

 

all or nothing

 

원자성은 트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았거나를 보장하는 특징이다.

예를 들어 트랜잭션을 커밋할 때 문제가 발생하여 롤백이 발생하는 경우 그 이후에 모두 수행되지 않음을

보장하는 것을 말한다.

또한, 트랜잭션 단위로 여러 로직들을 묶을 때 외부 API 를 호출하는 것이 있으면 안된다.

만약 있다면 롤백이 일어났을 때 어떻게 해야 할 것인지에 대한 해결 방법이 있어야 하고,

트랜잭션 전파를 신경 써서 관리해야 한다.

 

- 커밋과 롤백

커밋은 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어이다.

트랜잭션 단위로 수행되며 변경된 내용이 모두 영구적으로 저장되는 것을 말한다.

즉, 커밋이 수행 된 것은 하나의 트랜잭션이 성공적으로 수행되었다고 할 수 있다.

 

그러나 에러나 여러 이슈 때문에 트랜잭션 전으로 돌려야 할 때 롤백을 사용해야 한다.

롤백이란 트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 돌리는 일을 말한다.

 

이러한 커밋과 롤백 덕분에 데이터의 무결성이 보장된다.

또한, 데이터 변경 전에 변경 사항을 쉽게 확인 가능하고 해당 작업을 그룹화 할 수 있다.

 

- 트랜잭션 전파

트랜잭션을 수행할 때 connection 단위로 수행한다.

따라서 connection 객체를 넘겨서 수행해야 한다.

하지만 connection 객체를 넘겨서 수행하는 것은 번거로운 일이다.

따라서 넘겨서 수행하는 것이 아닌, 여러 트랜잭션 관련 메서드의 호출을 하나의 트랜잭션에 묶이도록 하며, 

이를 트랜잭션 전파라고 부른다.

@Service
@Transactional(readOnly = true)
public class MemberService {
	private final MemberRepository memberRepository;
    
    public MemberService(MemberRepository memberRepository) {
    	this.memberRepository = memberRepository;
    }
}

 

Spring 프레임 워크에서는 @Transactional 애너테이션을 통해 여러 쿼리 관련 코드들을 하나의

트랜잭션으로 처리한다.

 

 

※ 일관성 (Consistency)

 

일관성은 허용된 방식으로만 데이터를 변경하는 것을 말한다.

데이터베이스에 기록된 모든 데이터는 여러 가지 조건, 규칙에 따라 유효함을 가져야 한다.

예를 들어 A 라는 유저가 0 원을 보유하고 있을 때, B 라는 유저에게 10000 원을 입금한다고 해보자.

이 경우는 마이너스 통장이 되므로 불가능하다.

즉, 불가능한 경우를 방지하는 것이라고 할 수 있겠다.

 

 

※ 격리성 (Isolation)

 

격리성이란 트랜잭션 수행 시 서로 끼어들지 못하는 것을 의미한다.

복수의 병렬 트랜잭션은 서로 격리되어 마치 순차적으로 실행되는 것처럼 작동되어야 하고,

데이터베이스는 여러 사용자가 같은 데이터에 접근할 수 있어야 한다.

순차적으로 수행한다고 하면 쉽겠지만 성능이 나빠지는 이슈가 존재한다.

 

 

격리수준은 총 4가지 존재한다.

 

  1. Serializable : 발생 현상 x
  2. Repeatable Read : Phantom Read 발생
  3. Read Committed : Non-Repeatable Read + Phantom Read 발생
  4. Read Uncommitted : Dirty Read + Non-Repeatable Read + Phantom Read 발생

 

위 사진에서 오른쪽으로 갈수록 격리성이 강해지지만 동시성이 약해지고,

왼쪽으로 갈수록 동시성이 강해지지만 격리성이 약해진다.

예를 들어서 Read Uncommitted 는 동시성이 강한 반면에 격리성이 약하다.

 

- 격리 수준에 따라 발생하는 현상

격리 수준에 따라 발생하는 현상은 팬텀 리드, 반복 가능하지 않은 조회, 더티 리드 세 가지고 분류된다.

 

① 팬텀 리드 (Phantom Read)

 

 

팬텀 리드는 한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우를 말한다.

위 사진을 예로 본다면, 트랜잭션 1, 트랜잭션 2 에서 동일한 테이블을 참조한다고 생각해보자.

트랜잭션 1 에서 Item 3 을 추가하게 될 경우 커밋하기 전과 커밋하기 후에 따라 트랜잭션 2 에서의

조회 결과가 달라질 수 있다.

 

  • 커밋하기 전 : 여전히 반영되지 않은 테이블을 참조
  • 커밋하기 후 : 트랜잭션 1 에 대한 쿼리가 수행되어진(Insert) 테이블을 참조

 

② 반복 가능하지 않은 조회 (Non-Repeatable Read)

 

 

반복 가능하지 않은 조회는 한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생할 때,

그 값이 다른 경우를 가리킨다.

위 사진의 예로 본다면, 트랜잭션 1, 트랜잭션 2 에서 동일한 테이블을 참조한다고 생각해보자.

트랜잭션 1 에서 Item 2 를 Item 3 으로 변경하게 될 경우 커밋하기 전과 커밋하기 후에 따라

트랜잭션 2 에서의 동일한 행의 조회 결과가 달라질 수 있다.

 

  • 커밋하기 전 : 여전히 반영되지 않은 레코드를 반환
  • 커밋하기 후 : 트랜잭션 1 에 대한 쿼리가 수행되어진(Update) 테이블을 참조하여 반영된 레코드를 반환

 

- 팬텀 리드와 반복 가능하지 않은 조회의 차이점

 

  • 팬텀 리드 : 없던 레코드가 생기거나 있던 레코드가 사라지는 경우로 레코드의 존재 유무에 초점을 맞춘 것이다.
  • 반복 가능하지 않은 조회 : 조회된 레코드의 값이 다른 경우로 한 레코드의 값에 초점을 맞춘 것이다.

 

③ 더티 리드 (Dirty Read)

 

 

더티 리드는 반복 가능하지 않은 조회와 유사하며 한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만,

아직 커밋되지 않은 행의 데이터를 읽을 수 있을 때 발생한다.

위 사진의 예로 본다면, 트랜잭션 1, 트랜잭션 2 에서 동일한 테이블을 참조한다고 생각해보자.

트랜잭션 1 에서 Item 3 을 추가할 경우 트랜잭션 2 에서의 조회 결과가 트랜잭션 1 에서 추가했던 레코드가

반영되어 진다.

 

 

※ 격리 수준

 

- SERIALIZABLE

SERIALIZABLE 이란 트랜잭션을 순차적으로 진행시키는 것을 말한다.

여러 트랜잭션이 동시에 같은 행에 접근할 수 없다.

이 수준은 매우 엄격한 수준으로 해당 행에 대해 격리시키고, 이후 트랜잭션이 이 행에 대해 일어난다면

기다려야 한다.

따라서 교착 상태(deadlock)가 발생할 확률이 높아 성능이 떨어지는 격리 수준이다.

그대신 격리성이 최대인 만큼 안전성을 완전하게 보장할 수 있다.

 

- REPEATABLE_READ

REPEATABLE_READ 는 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주지만,

새로운 행을 추가하는 것을 막아주지는 못한다.

따라서 이후에 추가된 행이 발견될 수 있다.

 

- READ_COMMITTED

READ_COMMITTED 는 가장 많이 사용되는 격리 수준이다.

MySQL, PostgreSQL, SQL Server, Oracle 에서 기본값으로 설정되어 있다.

READ_UNCOMMITTED 와 달리 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없다.

즉, 커밋 완료된 데이터에 대해서만 조회가 허용된다.

 

- READ_UNCOMMITTED

READ_UNCOMMITTED 는 가장 낮은 격리 수준으로, 하나의 트랜잭션이 커밋되기 이전에

다른 트랜잭션에 노출되는 문제가 있지만 가장 빠르다.

데이터 무결성을 위해 되도록 사용하지 않는 것이 일반적이지만, 몇몇 행이 제대로 조회되지 않더라도

괜찮은 거대한 양의 데이터를 '어림잡아' 집계하는 데는 사용하면 좋다.

 

 

※ 지속성 (Durability)

 

지속성은 성공적으로 수행된 트랜잭션은 영원히 반영되어야 하는 것을 의미한다.

이는 데이터베이스에 시스템 장애가 발생해도 원래 상태로 복구하는 회복 기능이 있어야 함을 뜻하며,

데이터베이스는 이를 위해 체크섬, 저널링, 롤백 등의 기능을 제공한다.

 

  • 체크섬 : 중복 검사의 한 형태로, 오류 정정을 통해 송신된 자료의 무결성을 보호하는 방법
  • 저널링 : 파일 시스템 또는 데이터베이스 시스템에 변경 사항을 반영하기 전에 로깅하는 것, 트랜잭션 등 변경 사항에 대한 로그를 남기는 것

 

※ 무결성 (Integrity)

 

무결성이란 데이터의 정확성, 일관성, 유효성을 유지하는 것을 말한다.

무결성 종류로는 다음과 같다.

 

  • 개체 무결성 : 기본키로 선택된 필드는 빈 값을 허용하지 않는다.
  • 참조 무결성 : 서로 참조 관계가 있는 두 테이블의 데이터는 항상 일관된 값을 유지해야 한다.
  • 고유 무결성 : 특정 속성에 대한 고유한 값을 가지도록 조건이 주어진 경우, 그 속성 값은 모두 고유한 값을 가진다.
  • NULL 무결성 : 특정 속성 값에 NULL 이 올 수 없다는 조건이 주어진 경우, 그 속성 값은 NULL 이 될 수 없다는 제약 조건이다.

 

 

데이터베이스의 종류

 

※ 관계형 데이터베이스

 

관계형 데이터베이스는 행과 열을 가지는 표 형식 데이터를 저장하는 형태의 데이터베이스를 가리키며,

SQL 이라는 언어를 사용하여 조작한다.

MySQL, PostgreSQL, 오라클, SQL Server, MSSQL 등이 있다.

 

- MySQL 

대부분의 운영체제와 호환되며 가장 많이 사용되는 데이터베이스이다.

C, C++ 로 만들어지며 MyISAM 인덱스 압축 기술, B-트리 기반의 인덱스, 스레드 기반의 메모리 할당 시스템,

매우 빠른 조인, 최대 64개의 인덱스를 제공한다.

대용량 데이터베이스를 위해 설계되어 있으며 롤백, 커밋, 이중 암호 지원 보안 등의 기능을 제공하며

많은 서비스에서 제공된다.

 

- PostgreSQL

디스크 조각이 차지하는 영역을 회수할 수 있는 장치인 VACUUM 이 특징이다.

최대 테이블의 크기는 32TB 이며, SQL 뿐만 아니라 JSON 을 이용해서 데이터를 접근할 수 있다.

지정 시간에 복구하는 기능, 로깅, 접근 제어, 중첩된 트랜잭션, 백업 등을 할 수 있다.

 

 

※ NoSQL 데이터베이스

 

SQL 을 사용하지 않는 데이터베이스를 말하며, 대표적으로 MongoDB와 redis 등이 있다.

 

- MongoDB

JOSN 을 통해 데이터 접근이 가능하며, 바이너리 JSON 형태(BSON)로 데이터가 저장되며

와이어드타이거 엔진이 기본 스토리지 엔진으로 장착된 키-값 데이터 모델에서 확장된

도큐먼트 기반의 데이터베이스이다.

그리고 스키마를 정해 놓지 않고 데이터를 삽입할 수 있기 때문에 다양한 도메인의 데이터베이스를

기반으로 분석하거나 로깅 등을 구현할 때 강점을 보인다.

또한, MongoDB 는 도큐먼트를 생성할 때마다 다른 컬렉션에서 중복된 값을 지니기 힘든 

유니크한 값인 ObjectID 가 생성된다.

 

- redis

redis 는 인메모리 데이터베이스이며 키-값 데이터 모델 기반의 데이터베이스 이다.

기본적인 데이터 타입은 문자열이며 최대 512 MB 까지 저장이 가능하다.

이외에도 set, hash 등을 지원한다.

 

 

인덱스

 

※ B-트리

 

B-트리 참고하기 좋은 글, 정리가 너무 잘 되어있다!

https://rebro.kr/169?category=484170 

 

[DB] 10. B-Tree (B-트리)

[목차] 1. B-Tree란? 2. B-Tree의 key 검색 3. B-Tree의 key 삽입 4. B-Tree의 key 삭제 참고) emplam27.log 블로그 https://hyungjoon6876.github.io/jlog/2018/07/20/btree.html https://helloinyong.tistory.co..

rebro.kr

 

인덱스가 효율적인 이유는 효율적인 단계를 걸쳐서 모든 요소에 접근할 수 있는 균형 잡힌 트리 구조와

트리 깊이의 대수확장성 때문이다.

대수확장성이란 트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것을 의미한다.

 

 

※ 인덱스 만드는 방법

 

- MySQL

MySQL 의 경우 클러스터형 인덱스와 세컨더리 인덱스가 있다.

클러스터형 인덱스는 테이블당 하나를 설정할 수 있다.

primary key 옵션으로 기본키로 만들면 클러스터형 인덱스를 생성할 수 있고, 기본키로 만들지 않고

unique not null 옵션을 붙이면 클러스터형 인덱스로 만들 수 있다.

create index... 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있다.

하나의 인덱스만 생성할 것이라면 클러스터형 인덱스를 만드는 것이 세컨더리 인덱스를 만드는 것 보다 

성능이 좋다.

 

- MongoDB

도큐먼트를 만들면 자동으로 ObjectID 가 형성되며, 해당 키가 기본키로 설정된다.

그리고 세컨더리키도 부가적으로 설정하여 기본키와 세컨더리키를 같이 쓰는 복합 인덱스를 설정할 수 있다.

 

 

※ 인덱스 최적화 기법

 

MongoDB 를 기반으로 인덱스를 최적화하는 기법은 아래와 같다.

 

- 인덱스는 비용인덱스는 두 번 탐색하도록 강요한다.인덱스 리스트, 그 다음 컬렉션 순으로 탐색하기 때문이며, 관련 읽기 비용이 들게 된다.또한, 컬렉션이 수정될 때 인덱스도 수정되어야 한다.이때 B-tree 의 높이를 균형 있게 조절하는 비용이 들며, 데이터를 효율적으로 조회할 수 있도록분산시키는 비용도 들게 된다.따라서 쿼리에 있는 필드에 인덱스를 무작정 다 설정하는 것은 좋지 않다.또한, 컬렉션에서 가져와야 하는 양이 많을수록 인덱스를 사용하는 것은 비효율적이다.

 

- 테스팅은 필수서비스에서 사용하는 객체의 깊이, 테이블의 양 등이 다르기 때문에 서비스 특징에 따라 인덱스 최적화 기법이 다르다.따라서 항상 테스팅하는 것이 중요하다.

 

- 복합 인덱스는 같음, 정렬, 다중 값, 카디널리티 순보통 여러 필드를 기반으로 조회를 할 때 복합 인덱스를 생성하는데, 이 인덱스를 생성할 때는 순서가 있고 생성 순서에따라 인덱스 성능이 달라진다.같음, 정렬, 다중 값, 카디널리티 순으로 생성해야 한다.

 

  1. 어떠한 값과 같음을 비교하는 ==, equal 쿼리가 있다면 제일 먼저 인덱스로 설정한다.
  2. 정렬에 쓰이는 필드라면 그 다음 인덱스로 설정한다.
  3. 다중 값을 출력해야 하는 필드, 즉 쿼리 자체가 > 이거나 < 등 많은 값을 출력해야 하는 쿼리에 쓰는 필드라면 나중에 인덱스를 설정한다.
  4. 유니크한 값의 정도를 카디널리티라고 한다. 카디널리티가 높은 순서를 기반으로 인덱스를 생성해야 한다. (ex : age, email 둘 중 email 필드에 대한 인덱스를 먼저 생성)

 

 

조인의 원리 

 

※ 중첩 루프 조인

중첩 루프 조인(NLJ, Nested Loop Join)은 중첩 for 문과 같은 원리로 조건에 맞는 조인을 하는 방법이며,

랜덤 접근에 대한 비용이 많이 증가하므로 대용량 테이블에서 사용하지 않는다.

예를 들어 두 테이블을 조인할 때 첫 테이블에서 행을 한 번에 하나씩 읽고 그 다음 테이블에서도 행을 하나씩 읽어

조건에 맞는 레코드를 찾아 결괏값을 반환한다.

for each row in t1 matching reference key {
	for each row in t2 matching reference key {
    	if row satisfies join conditions, send to client
    }
}

 

참고로 중첩 루프 조인에서 발전한 조인할 테이블을 작은 블록으로 나눠서 블록 하나씩 조인하는 블록 중첩 루프 조인

(BNL, Block Nested Loop) 이라는 방식도 있다.

 

 

 

 정렬 병합 조인

 

각각의 테이블을 조인할 필드 기준으로 정렬 후, 정렬이 끝난 이후에 조인을 하는 방법이다.

조인할 때 쓸 적절한 인덱스가 없고 대용량의 테이블들을 조인하고 조인 조건으로 <, > 등

범위 비교 연산자가 있을 때 씁니다.

 

 

※ 해시 조인

 

해시 테이블을 기반으로 조인하는 방법이다.

두 개의 테이블을 조인한다고 했을 때 하나의 테이블이 메모리에 온전히 들어가게 된다면

보통 중첩 루프 조인보다 더 효율적이다.

또한, 동등(=) 조인에서만 사용할 수 있다.

MySQL 의 경우 이 기능을 사용할 수 있으며 해시 조인 단계로 빌드 단계, 프로브 단계로 나뉜다.

 

- 빌드 단계

입력 테이블 중 하나를 기반으로 메모리 내 해시 테이블을 빌드하는 단계이다.

예를 들어 A, B 테이블을 조인한다고 할 때, 둘 중에 바이트가 더 작은 테이블을 기반으로

해시 테이블을 빌드하게 된다.

 

 

또한, 조인에서 사용되는 필드가 해시 테이블의 키로 사용되게 된다.

즉, B 테이블의 b_id 가 키로 사용되게 된다.

 

- 프로브 단계

프로브 단계 동안 레코드 읽기를 시작하며, 각 레코드에서 A.b_id 에 일치하는 레코드를 찾아서

결괏값을 반환하게 된다.

 

 

이를 통해 각 테이블은 한 번씩만 읽게 되어 중첩해서 두 개의 테이블을 읽는 중첩 루프 조인보다

보통은 성능이 더 좋다.

참고로 사용 가능한 메모리양은 시스템 변수 join_buffer_size 에 의해 제어되며, 런타임 시

조절이 가능하다.

 

'Computer Science > 데이터베이스' 카테고리의 다른 글

Anomaly, Index  (0) 2022.03.02
데이터베이스  (0) 2022.03.02
Redis  (0) 2022.03.01
Transaction  (0) 2022.02.28
Normalization  (0) 2022.01.21
Comments