[CS] 데이터베이스

Swim Lee·2021년 6월 30일
0

기술면접 대비

목록 보기
12/13

데이터베이스

참고할 링크 :
DBMS가 트랜잭션 관리하는 방법 - 네이버 D2
트랜잭션 격리 수준과 Lock - MySQL

두 개 같이보면 이해 쉬울듯

아래 링크에서 왜 Consistent Read와 Read Uncommitted로 인한 Dirty Read가 발생하는지를 위의 링크에서 DBMS의 버퍼관리자의 버퍼관리 정책을 보면 알 수 있다.

대부분의 DBMS가 꼭 트랜잭션이 커밋되는 시점에 메모리 버퍼의 내용이 디스크에 적히는 것이 아니라 언제든지 버퍼의 내용이 디스크에 쓰일 수 있는 Steal 정책을 따르기 때문.

그냥 내 궁예질이긴 하지만 어쨌든 REDO 로그와 UNDO 로그를 이용해서 DB의 일관성을 유지한다는 뜻!

아래 링크에서 Consistent Read를 하는 것도 로그를 이용해서 특정 시점의 DB 스냅샷을 복구하는 개념이니 그정도 맥락으로만 이해하도록 하자

사용이유

데이터베이스 사용 전에는 파일 시스템을 이용하여 데이터를 관리했음. (현재도 부분적으로 사용) 데이터를 각각의 파일 단위로 저장하며 이러한 일들을 처리하기 위한 독립적인 애플리케이션과 상호 연동이 되어야한다. 이 때의 문제점은 "데이터 종속성 문제"와 "중복성", "데이터 무결성"이다.

데이터베이스 특징

1. 데이터 독립성

  • 물리적 독립성 : 데이터 베이스 사이즈를 늘리거나, 성능 향상을 위해 데이터 파일을 늘리거나 새롭게 추가하더라도 관련된 응용 프로그램을 수정할 필요가 없다.
  • 논리적 독립성 : 데이터베이스는 논리적인 구조로 다양한 응용프로그램의 논리적 요구를 만족시켜줄 수 있다.

2. 데이터 무결성 보장

여러 경로를 통해 잘못된 데이터가 발생하는 경우의 수를 방지하는 기능.
데이터 유효성 검사를 통해 데이터의 무결성을 구현

3. 데이터 보안성

인가된 사용자들만 데이터베이스나 데이터베이스 내의 자원에 접근할 수 있도록 계정관리 또는 접근 권한을 설정함으로써 모든 데이터에 보안을 구현할 수 있음

4. 데이터의 일관성

연관된 정보를 논리적인 구조로 관리함으로서 어떤 하나의 데이터만 변경했을 경우 발생할 수 있는 데이터의 불일치성을 배제할 수 있음. 또한 작업 중 일부 데이터만 변경되어 나머지 데이터와 일치하지 않는 경우의 수를 배제할 수 있다.

5. 데이터 중복 최소화

데이터를 통합해서 관리함으로서 파일 시스템의 단점 중 하나인 데이터의 중복 문제를 해결할 수 있음.

데이터베이스 성능

참고하기 :
http://wiki.gurubee.net/pages/viewpage.action?pageId=26739100

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=itperson&logNo=220877951995

데이터베이스의 성능 이슈는디스크 I/O를 어떻게 줄이느냐에서 시작됨.

디스크 I/O란 디스크 드라이브의 플래터(원판)을 돌려서 읽어야할 데이터가 저장된 위치로 디스크 헤더를 이동시킨 다음 데이터를 읽는 것을 의미한다. 이 때 데이터를 읽는데 걸리는 시간은 디스크 헤더를 움직여서 읽고 쓸 위치로 옮기는 단계에서 결정된다. 즉, 디스크의 성능은 디스크 헤더의 위치 이동 없이 얼마나 많은 데이터를 한번에 기록하느냐에 따라 결정된다.

디스크의 입출력 IO의 경우 블록(오라클은 블록, 나머지는 페이지) 단위로 이루어진다. 블록단위로 I/O를 한다는 것은, 하나의 레코드에서 하나의 컬럼만들 읽으려할 때도 레코드가 속한 블록 전체를 읽게 됨을 의미한다.

Sequential Access : 하나의 블록을 엑세스해서 그 안에 저장되어있는 모든 레코드를 순차적으로 읽어들이는 것. 무거운 디스크 I/O를 수행하더라도 비효율은 없다.

Random Access : 레코드 하나를 읽으려고 블록을 통채로 엑세스하는 것. 메모리 버퍼에서 읽더라도 비효율이 존재한다.

그렇기 때문에 순차 I/O가 랜덤 I/O보다 빠를 수밖에 없다. 하지만 현실에서는 대부분 I/O작업이 랜덤 I/O이다. 랜덤 I/O를 순차 I/O로 바꿔서 실행할 수 없을까? 이러한 생각에서부터 시작되는 데이터베이스 쿼리 튜닝은 랜덤 I/O자체를 줄여주는 것이 목적이라 할 수 있다.

인덱스

사전적 의미는 색인. 즉 찾고자 하는 내용을 빠르게 찾을 수 있도록 도와주는 도구. 책의 맨 처음 또는 맨 마지막에 있는 색인이 그러한 역할임. 이 비유를 그대로 가져와서 인덱스를 살펴보면, 데이터는 책의 내용이고, 데이터가 저장된 레코드의 주소는 인덱스 목록에 있는 페이지 번호가 될 것임. DBMS도 데이터베이스 테이블의 모든 데이터를 검색해서 원하는 결과를 가져오려면 시간이 오래걸림 (full scan) 그래서 "컬럼"의 값과 해당 레코드가 저장된 주소를 "키와 값의 쌍"으로 인덱스를 만들어두는 것

DBMS의 인덱스는 항상 정렬된 상태를 유지하기 때문에 원하는 값을 탐색하는데는 빠르지만, 새로운 값을 추가하거나 삭제, 수정하는 경우에는 쿼리문 실행 속도가 느려짐. 결론적으로 DBMS에서 인덱스는 "데이터 저장성능을 희생"하고 그 대신 "데이터 읽기 속도"를 높이는 기능.

SELECT 쿼리문의 WHERE 조건절에 사용되는 컬럼이라고 전부 인덱스로 생성하면 데이터 저장성능이 떨어지고, 인덱스의 크기가 비대해져서 오히려 역효과만 불러올 수 있다.

인덱스 자료구조

B+ Tree 인덱스

일반적으로 사용되는 인덱스 알고리즘은 B+ Tree 알고리즘임. B+ Tree 인덱스는 컬럼의 값을 변경하지 않고 (사실 값의 앞부분만 잘라서 관리한다고함) 원래의 값을 이용해 인덱싱하는 알고리즘

Hash 인덱스

컬럼의 값으로 해시 값을 계산해서 인덱싱하는 알고리즘. 매우 빠른 검색 지원 O(1)이기 때문. 하지만 "값을 변형"해서 인덱싱하므로, 특정 문자로 시작하는 값으로 검색하는 전방일치와 같이 값의 일부만으로 검색하고자 할 때는 해시 인덱스를 사용할 수 없다. 주로 메모리 기반의 데이터베이스에서 많이 사용.

왜 인덱스 생성에 B-tree를 사용하는가?

데이터에 접근하는 시간복잡도가 O(1)인 해시 테이블이 더 효율적이지 않나? SELECT 질의 조건에는 부등호 연산도 포함이 된다. 해시테이블을 사용한다면, 등호연산이 아닌 부등호 연산의 경우에 문제가 발생. 동등 연산에 특화된 해시테이블은 데이터베이스의 자료구조로 적합하지 않음.

Primary Index vs Secondary Index

클러스터(Cluster)란 여러 개를 하나로 묶는다는 의미로 주로 사용되는데, 클러스터드 인덱스도 크게 다르지 않음. 인덱스에서 클러스터드는 비슷한 것들을 묶어서 저장하는 형태로 구현. 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에서 착안된 것. 여기서 비슷한 값들은 물리적으로 인접한 장소에 저장되어있는 데이터들을 의미.

클러스터드 인덱스는 테이블의 프라이머리 키에 대해서만 적용되는 내용. 즉, 프라이머리 키 값이 비슷한 레코드끼리 묶어서 저장하는 것을 클러스터드 인덱스라고 표현. 클러스터드 인덱스에는 프라이머리 키 값에 의해 레코드의 저장위치가 결정되며, 프라이머리 키 값이 변경되면 그 레코드의 물리적인 저장위치 또한 변경되어야한다. 그렇기 때문에 프라이머리 키를 신중하게 결정하고 클러스터드 인덱스를 사용해야한다.

클러스터드 인덱스는 테이블당 하나만 생성할 수 있음. 프라이머리 키에 대해서만 적용되기 때문. 이에 반해 non-clustered index의 경우 테이블당 여러개 생성 가능.

참고: https://lng1982.tistory.com/144

Composite Index

인덱스로 설정하는 필드의 속성이 중요. 복합인덱스의 경우 인덱스로 설정하는 컬럼의 순서또한 중요함. 인덱스로 정의한 속성의 순서대로 search를 하기 때문.

Index의 성능과 고려해야할 사항

SELECT 쿼리 성능을 월등히 향상 시키는 INDEX는 항상 좋은가? 그렇다면 모든 컬럼에 Index를 생성해두면 좋은 것 아닌가? 그렇지 않다.

Index를 생성하게 되면 Insert, Delete, Update 쿼리문을 실행할 때 별도의 추가적인 과정이 발생하게 된다. Insert의 경우 테이블 뿐만 아니라 Index에 대한 데이터도 추가해야하므로 그만큼 성능에 손실이 따른다.
Delete의 경우 Index에 존재하는 값은 삭제하지 않고 사용안함 표시만한다. 즉, Index의 row의 수는 그대로이다. 이 작업이 계속 반복된다면 실제 데이터는 10만건인데, Index row수는 100만건이 있는 결과가 나올 수도 있다. 이렇게 되면 인덱스는 더이상 제 역할을 하지 못한다. (조회 속도 향상이라는 본래의 기능을 수행할 수 없다.)

Update의 경우 Insert와 Delete의 문제점을 동시에 발생시킨다. 이전 데이터가 삭제되고 새로운 데이터를 삽입하는 개념이기 때문이다. 변경 전 데이터는 삭제되지 않고 Insert로 인한 Split도 발생하게 된다.

cf) Index split이란? 인덱스의 Block들이 하나에서 두개로 나누어지는 현상. 인덱스는 데이터가 순서대로 정렬되어야하는데, 기존 블록에 여유공간이 없는 상황에서 그 블록에 새로운 데이터가 입력되어야할 경우, 기존 블록의 내용 중 일부를 새로운 블록에다가 기록한 후 기존 블록에 빈 공간을 만들어서 새로운 데이터를 추가하게 된다.

이는 성능면에서 매우 불리한데, 그 이유는 첫 번째로 Index split은 새로운 블록을 할당받고 key를 옮기는 복잡한 작업을 수행하며, 모든 수행 과정이 Redo에 기록되기 때문에 많은 양의 Redo를 유발한다. 두번째로, Index Split이 이루어지는 동안 해당 블록에 대해 키값이 변경되면 안되므로 DML이 블로킹된다.

추가로, 데이터베이스 블록이란, 디스크(데이터베이스)에 쓰여지는 데이터의 최소단위를 뜻한다. DB에 데이터는 블록단위로 IO가 발생한다. (오라클의 경우 블록, 다른 DBMS에서는 페이지라는 단위를 사용한다고 한다.)

하지만, 더 중요한 것은 컬럼을 이루고 있는 데이터의 형식에 따라서 인덱스의 성능에 악영향을 미칠 수 있다는 것이다. 즉, 데이터의 형식에 따라 인덱스를 만들면 효율적이고 만들면 비효율적인 데이터의 형식이 존재한다. 값의 range가 적은 성별, 나이 같은 경우 인덱스를 읽고 다시 한번 디스크 I/O가 발생하기 때문에 그만큼 비효율적이다. (range가 적으면 그냥 바로 인덱스 조회 과정없이 디스크 I/O를 수행하는 것이 더 효율적, 어차피 중복되는 값이 많기 때문에 굳이 인덱싱할 이유가 없음)


추가적으로 다시 정리하면
인덱스는 B+ Tree 알고리즘을 사용하여서 항상 정렬된 상태를 유지한다.

B+ Tree는 확장된 균형 이진탐색 트리 형태이기 때문에, 기본적으로 정렬되어서 저장된다. 이로 인해 O(N)의 시간 복잡도인 full scan을 하지 않고 O(logN)의 시간복잡도로 조회 속도를 향상시킬 수 있지만, 잦은 테이블의 변경(삽입, 삭제, 수정)가 일어난다면 인덱스의 테이블을 변경과 정렬에 드는 오버헤드 때문에 오히려 성능저하가 일어날 수 있다.

  • Insert : 테이블에는 "입력 순서대로 저장"하기 때문에 O(1)이지만, 인덱스 테이블은 정렬된 상태로 저장해야하기 때문에 O(logN)의 시간복잡도 발생
  • Delete : 테이블에서만 삭제되고 인덱스 테이블에는 사용안함 표시되기 때문에 그대로 남아있어서 쿼리 수행속도를 저하시킨다.
  • Update : 인덱스 테이블에는 Update가 없으므로 Delete후 Insert되어 두 작업에서 일어나는 문제가 동시에 발생한다.

데이터의 중복이 높은 컬럼(카디널리티 - 중복 제거한 개수 - 가 낮은 컬럼)은 인덱스로 만들어도 무용지물이다. (예: 성별)

다중 컬럼 인덱싱할 때 카디널리티가 높은 컬럼 -> 낮은 컬럼 순으로 인덱싱해야 효율적이다. (그래야 일치하는 거 찾을 때 탐색 범위가 확확 줄어들기 때문이다. 중복되는 값이 많으면 그만큼 적게 줄어든다.)

정규화

정규화 생성 배경

한 릴레이션에 여러 엔티티의 애트리뷰트들을 혼합하게 되면 정보가 중복 저장되며, 저장공간을 낭비하게 된다. 또 중복된 정보로 인해 삽입, 삭제, 갱신이상이 발생한다. 동일한 정보를 한 릴레이션에서는 변경하고, 나머지 릴레이션에서는 변경하지 않은 경우 어느 것이 정확한지 알 수 없게된다.

정규화는 이러한 이상현상이 발생하지 않도록 릴레이션을 관련이 있는 속성들로만 구성하기 위해 "분해"하는 과정이다.

정규화 과정에서 고려해야하는 "속성들간의 관련성"을 "함수적 종속성"이라고 한다. 일반적으로 릴레이션에 함수적 종속성이 "하나" 존재하도록 정규화를 통해 릴레이션을 분해한다.

함수적 종속성을 하나만 포함하면 이상현상이 발생하지 않는다. 하지만 함수적 종속성을 여러 개 포함하면 이상현상이 발생할 수 있다.

릴레이션을 분해할 때 주의할 점은, 분해된 릴레이션을 자연 조인하여 분해전의 릴레이션으로 다시 복원할 수 있어야한다! 이러한 분해를 무손실 분해라고 한다. 정규화 과정에서 수행되는 릴레이션의 분해는 무손실 분해여야함을 기억하자!

삽입이상

원하지 않는 자료가 삽입된다든지, 삽입하는데 자료가 부족해 삽입이 되지 않아 발생하는 문제점.

삭제이상

하나의 자료만 삭제하고 싶지만, 그 자료가 포함된 튜플 전체 데이터가 삭제됨으로 원하지 않는 정보 손실이 발생하는 문제점

갱신이상

정확하지 않거나 일부의 튜플만 갱신되어 정보가 모호해지거나 일관성이 없어져 정확한 정보파악이 되지 않는 문제점

정규화란

관계형 데이터베이스에서 데이터의 중복을 최소화하기 위해 데이터를 구조화하는 작업. 함수적 종속성을 이용하여 릴레이션을 연관성이 있는 속성들로만 구성되도록 "분해"해서 이상현상이 발생하지 않는 올바른 릴레이션으로 만들어나가는 과정을 정규화라고 한다. 정규화의 기본 목표는 관련이 없는 함수 종속성은 별개의 릴레이션으로 표현하는 것이다.

릴레이션의 정규화 정도는 "정규형"으로 표현한다. 정규형은 크게 기본 정규형과 고급 정규형으로 나눈다. 기본 정규형에는 제 1, 2, 3, 보이스코드 정규형이 있고, 고급 정규형에는 제 4, 5 정규형이 있다.

각 정규형마다 만족시켜야하는 제약조건이 존재한다. 릴레이션이 특정 정규형의 제약조건을 만족하면 릴레이션이 해당 정규형에 속한다고 표현한다. 정규형의 차수가 높아질 수록 요구되는 제약조건이 많아지고 엄격해진다. 일반적으로는 기본 정규형에 속하도록 릴레이션을 정규화하는 경우가 대부분이다.

제 1 정규형

릴레이션에 속한 모든 속성의 도메인이 원자값으로만 구성되어있다.

제 2 정규형

릴레이션이 제 1 정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 대해 완전함수적 종속되면 제 2 정규형이다.

제 3 정규형

릴레이션이 제 2 정규형에 속하고, 기본키가 아닌 모든 속성이 기본키에 이행적 함수종속이 되지 않으면 제 3 정규형에 속한다.

함수적 종속관계를 "여러 개 포함"하고 있으면 "이행적 함수 종속"이 생기기 때문에 이상현상이 발생할 수 있다. 릴레이션을 분해하여 이행적 함수 종속을 제거하면 분해된 릴레이션은 제 3 정규형에 속하고 이상현상이 제거된다.

보이스코드 정규형

릴레이션의 함수 종속 관계에서 모든 결정자가 후보키이면 보이스 코드 정규형에 속한다. (결정자는 X->Y에서 X가 결정자 Y가 종속자)

후보키는 기본키가 될 수 있는 후보인 키들을 말한다. 여러 후보키가 존재하는 릴레이션에 해당되는 정규화 내용이다. 복잡한 식별자 관계에 의해 발생하는 문제를 해결하기 위해 제 3 정규형을 보완하는데 의미가 있다. 후보키가 아닌 키가 후보키의 일부를 결정하는 것을 분해하는 과정을 말한다.

정규화 장점

  • 데이터 베이스 변경시 이상현상 제거
  • 데이터 베이스 확장시 재 디자인 최소화
    • 정규화된 데이터베이스 구조에서는 새로운 데이터형의 추가로 인한 확장시, 그 구조를 변경하지 않아도 되거나 일부만 변경해도된다. 이는 데이터베이스와 연동된 응용프로그램에 최소한의 영향만을 미치게 되며 응용프로그램의 생명을 연장시킨다.

정규화 단점

릴레이션의 분해로 인해 릴레이션간 JOIN 연산이 많아진다. 이로 인해 질의에 대한 응답시간이 느려질 수 있다.

추가로 정규화를 수행하는 것은 데이터를 결정하는 결정자에 의해 함수적 종속을 갖는 일반 속성을 종속자(의존자)로 하여 이상현상을 제거하는 것이다.

데이터의 중복 속성을 제거하고 결정자에 의해 동일한 의미의 일반 속성이 "하나의 테이블로 집약" (하나의 테이블은 연관된 속성들로만 구성됨) 되므로 한 테이블의 데이터 용량이 최소화되는 효과가 있다.

따라서 정규화된 테이블은 데이터를 처리할 때 속도가 빨라질 수도 있고, 느려질 수도 있다는 특성이 있다.

정규화 진행해야하는 상황? 단점에 대한 대응책?

반정규화

반정규화는 정규화된 엔티티, 속성, 관계를 시스템의 성능 향상 및 개발과 운영의 단순화를 위해 중복, 통합, 분리 등을 수행하는 데이터 모델링 기법.

디스크 I/O양이 많아 조회시 성능이 저하되거나, 테이블끼리의 경로가 너무 멀어 조인으로 인한 성능저하 예상되거나, 컬럼을 계산하여 조회할 때 성능이 저하될 것이 예상되는 경우 반정규화를 수행하게 된다. 일반적으로 조회에 대한 성능이 중요하다고 판단될 때 부분적으로 반정규화를 고려하게 된다.

트랜잭션

트랜잭션은 작업의 완전성을 보장해주는 것. 즉, 논리적인 작업 셋을 모두 완벽하게 처리하거나 또는 처리하지 못할 경우에는 원 상태로 복구시켜서 작업의 일부만 적용되는 현상이 발생하지 않도록 만들어주는 기능. 데이터베이스 작업의 최소 단위. 사용자 입장에서는 작업의 논리적인 단위로 이해할 수 있고, 시스템의 입장에서는 데이터들을 접근 또는 변경하는 프로그램의 단위가 된다.

트랜잭션과 Lock

Lock은 트랜잭션 수행의 동시성을 제어하기 위한 기능이고, 트랜잭션은 데이터의 정합성을 보장하기 위한 기능.

잠금은 여러 커넥션에서 동시에 동일한 자원을 요청할 경우, 순서대로 한 시점에는 하나의 커넥션만 변경할 수 있게 해주는 역할을 한다. 여기서 자원은 레코드(테이블안의 데이터)나 테이블을 말한다.

이와는 다르게 트랜잭션은 꼭 여러개의 변경 작업을 수행하는 쿼리가 조합되었을 때만 의미있는 개념은 아니다. 트랜잭션은 하나의 논리적인 작업 셋중에 하나의 쿼리가 있든 두개의 쿼리가 있든 관계없이 논리적인 작업 셋 자체가 100% 적용되거나 아무것도 적용되지 않아야함을 보장하는 것이다.

트랜잭션 특성 ACID

  • Atomicity : 원자성, All or Nothing
  • Consistency : 일관성, 트랜잭션 수행 전후 데이터의 일관성이 보장되어야함.
  • Isolation : 고립성, 하나의 트랜잭션이 수행되는 동안, 다른 트랜잭션의 영향을 받지 않아야함.
  • Durability : 지속성, 트랜잭션의 수행 결과는 데이터베이스에 영구적으로 반영되어야한다.

트랜잭션 상태

  • Active : 트랜잭션이 실행중이며 동작중인 상태
  • Failed : 트랜잭션 실패 상태
  • Partially Committed : 트랜잭션의 Commit 명령이 도착한 상태, 트랜잭션의 commit 이전 sql문이 수행되고, commit만 남은 상태를 말한다.
  • Committed : 트랜잭션 완료상태. 트랜잭션이 정상적으로 완료된 상태를 말함
  • Aborted : 트랜잭션 취소상태. 트랜잭션이 취소되고 트랜잭션 실행 이전 데이터로 돌아간 상태.

Partially Committed와 Committed 차이

Commit 요청이 들어오면 트랜잭션의 상태는 Partially Committed가 된다. 이후 Commit을 문제없이 수행할 수 있으면 Committed 상태로 전이가 되고, 만약 오류가 발생하면 Failed 상태가 된다. 즉, Partially Committed는 Commit 요청이 들어왔을 때를 말하며, Committed는 Commit을 정상적으로 완료한 상태를 말한다.

트랜잭션 사용시 주의점

트랜잭션은 꼭 필요한 최소한의 코드에만 적용하는 것이 좋다. 즉, 트랜잭션의 범위를 최소화하라는 의미.

일반적으로 데이터베이스 커넥션은 개수가 제한적이다. 그런데, 각 단위 프로그램이 커넥션을 소유하는 시간이 길어진다면 사용가능한 여유 커넥션의 개수는 줄어들게 된다. 그러다 어느 순간에는 각 단위 프로그램에서 커넥션을 가져가기 위해 기다려야하는 상황이 발생할 수 있다.

교착상태

복수의 트랜잭션을 사용하다보면 교착상태가 일어날 수 있다. 교착상태란 두 개 이상의 트랜잭션이 특정 자원(테이블 또는 행)의 잠금(Lock)을 획득한 채 다른 트랜잭션이 소유하고 있는 Lock을 요구하면 아무리 기다려도 상황이 바뀌지 않는 상태가 되는데, 이를 교착상태라고 한다.

NoSQL

정의

관계영 데이터 모델을 "지양"하며 "대량의 분산된 데이터"를 저장하고 조회하는데 특화되어있으며 스키마 없이 사용가능하거나 느슨한 스키마를 제공하는 저장소

종류마다 쓰기/읽기 성능 특화, 2차 인덱스 지원, 오토 샤딩 지원 같은 고유한 특징을 가진다. 대량의 데이터를 빠르게 처리하기 위해 메모리에 임시 저장하고 응답하는 등의 방법을 사용한다. 동적인 스케일 아웃을 지원하기도 하며, 가용성을 위하여 데이터 복제 등의 방법으로 관계형 데이터베이스가 제공하지 못하는 성능과 특징을 제공한다.

CAP 이론

1. Consistency (일관성)

일관성은 동시성 또는 동일성이라고도 하며 "다중 클라이언트"에서 같은 시간에 조회하는 데이터는 항상 동일한 데이터임을 보증하는 것을 의미한다. (Repeatable Read? 와도 살짝 비슷한 느낌인듯) 이것은 관계형 데이터베이스가 지원하는 가장 기본적인 기능이지만, 일관성을 지원하지 않는 NoSQL을 사용한다면 데이터의 일관성이 느슨하게 처리되어 동일한 데이터가 나타나지 않을 수 있다. 느슨하게 처리된다는 것은 데이터의 변경을 시간의 흐름에 따라 "여러 노드에 전파"하는 것을 말한다. 이러한 방법을 최종적으로 일관성이 유지된다고 하여 최종 일관성 또는 궁극적 일관성을 지원한다고 한다.

각 NoSQL들은 분산 노드간의 데이터 동기화를 위해서 두가지 방법을 사용한다. 첫번째로 데이터의 저장결과를 클라이언트로 응답하기 전에 모든 노드에 데이터를 저장하는 동기식 방법이 있다. 그만큼 느린 응답시간을 보이지만 데이터의 정합성을 보장한다. 두번째로는 메모리나 임시 파일에 기록하고 클라이언트에 먼저 응답한 다음, 특정 이벤트 또는 프로세스를 사용하여 노드로 데이터를 동기화하는 비동기식 방법이 있다. 빠른 응답시간을 보인다는 장점이 있지만, 쓰기 노드에 장애가 발생했을 경우 데이터가 손실될 수 있다.

2. Availability 가용성

가용성이란 모든 클라이언트의 읽기와 쓰기 요청에 대하여 항상 응답이 가능해야함을 보증하는 것이며 내고장성(고장에대한 내성)이라고도 한다. 내고장성을 가진 NoSQL은 클러스터 내에서 몇 개의 노드가 망가지더라도 정상적인 서비스가 가능하다.

몇몇 NoSQL은 가용성을 보장하기 위해 데이터 복제(Replication)을 사용한다. 동일한 데이터를 다중 노드에 중복 저장하여 그 중 몇 대의 노드가 고장나도 데이터가 유실되지 않도록하는 방법이다. 데이터 중복 저장 방법에는 동일한 데이터를 가진 저장소를 하나 더 생성하는 Master-Slave 복제 방법과 데이터 단위로 중복 저장하는 Peer to Peer 복제 방법이 있다.

3. Partition Tolerance 네트워크 분할 허용성

분할 허용성이란 지역적으로 분할된 네트워크 환경에서 동작하는 시스템에서 두 지역간의 네트워크가 단절되거나 네트워크의 유실이 일어나더라도 각 지역내의 시스템은 정상적으로 동작해야함을 의미한다.

저장방식에 따른 NoSQL 분류

key Value Model, Document Model, Column Model, Graph Model로 분류할 수 있다.

1. Key Value Model

가장 기본적인 형태의 NoSQL이며 키 하나로 데이터 하나를 저장하고 조회할 수 있는 단일 키 값 구조를 갖는다. 단순한 저장구조로 인하여 복잡한 조회 연산을 지원하지 않는다. 또한 고속읽기와 고속쓰기에 최적화된 경우가 많다. 사용자의 프로필 정보, 웹 서버의 클러스터를 위한 세션정보, 장바구니 정보, URL 단축 정보 저장 등에 사용한다. 하나의 서비스 요청에 다수의 데이터 조회 및 수정 연산이 발생하면 트랜잭션 처리가 불가능하여 데이터 정합성을 보장할 수 없다.

ex) Redis

2. Document Model

키-값 모델을 개념적으로 확장한 구조로 하나의 키에 하나의 구조화된 문서를 저장하고 조회한다. 논리적인 데이터 저장과 조회 방법이 관계형 데이터베이스와 유사하다. 키는 문서에 대한 ID로 표현된다. 또한 저장된 문서를 컬렉션으로 관리하며 문서 저장과 동시에 문서 ID에 대한 인덱스를 생성한다. 문서 ID에 대한 인덱스를 사용하여 O(1)시간 안에 문서를 조회할 수 있다.

대부분의 문서 모델 NoSQL은 B트리 인덱스를 사용하여 2차 인덱스를 생성한다. B트리는 크기가 커지면 커질수록 새로운 데이터를 입력하거나 삭제할 때 성능이 떨어지게 된다. 그렇기 대문에 읽기와 쓰기의 비율이 7:3 정도일 때 가장 좋은 성능을 보인다. 중앙집중식 로그 저장, 타임라인 저장, 통계정보 저장 등에 사용된다.

ex) MongoDB

3. Column Model

하나의 키에 여러 개의 "컬럼 이름과 컬럼 값의 쌍"으로 이루어진 데이터를 저장하고 조회한다. 모든 컬럼은 항상 타임 스탬프 값과 함께 저장된다.

구글의 빅테이블이 대표적인 예로 차우 컬럼형 NoSQL은 빅테이블의 영향을 받았다. 이러한 이유로 Row Key, Column Key, Column Family 같은 빅테이블 개념이 공통적으로 사용된다. 저장의 기본 단위는 컬럼으로 컬럼은 이름과 컬럼 값, 타임스탬프로 구성된다. 이러한 컬럼들의 집합이 로우(Row)이며, 로우키(Row Key)는 각 로우를 유일하게 식별하는 값이다. 이러한 로우들의 집합은 키 스페이스(Key Space)가 된다.

대부분의 컬럼모델 NoSQL은 쓰기와 읽기중에 쓰기에 더 특화되어있다. 데이터를 먼저 커밋로그와 메모리에 저장한 후 응답하기 때문에 빠른 응답속도를 제공한다. 그렇기 때문에 일기연산 대비 쓰기 연산이 많은 서비스나 빠른 시간안에 대량의 데이터를 입력하고 조회하는 서비스를 구현할 때 가장 좋은 성능을 보인다. 채팅 내용 저장, 실시간 분석을 위한 데이터 저장소 등의 서비스 구현에 적합하다.


정리해놓은거 다날라감 ㅎㅎ;;

https://github.com/WeareSoft/tech-interview/blob/master/contents/db.md#%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%92%80

암튼 중요한 링크 첨부

: https://suhwan.dev/2019/06/09/transaction-isolation-level-and-lock/

위에게 트랜잭션 Isolation Level이랑 Lock 관련 정리 가장 깔끔하게 해놓은 글

진짜 좋으니까 다시한번 첨부했다 맨위에도 적어놓긴함


파티셔닝

배경

  • 서비스의 크기가 점점 커지고 DB에 저장되는 데이터의 규모 또한 대용량화 되면서, 기존에 사용하는 DB 시스템의 용량(Storage)의 한계와 성능(Performance)의 저하를 가져오게됨
  • 즉 VLDB(Very Large DBMS)와 같이 하나의 DBMS에 너무 큰 Table이 들어가면서 용량과 성능측면에서 많은 이슈가 발생하게 되었고, 이런 이슈를 해결하기 위한 방법으로 Table을 파티션(Partition)이라는 작은 단위로 나누어 관리하는 파티셔닝이라는 기법이 나타남

개념

  • "큰 테이블"이나 "인덱스"를 관리하기 쉬운 파티션이라는 작은 단위로 "물리적으로 분할"하는 것을 의미
  • 물리적인 분할이 있더라도 이를 사용하는 애플리케이션 입장에서는 이를 인식하지 못해야함
  • 파티셔닝 기법을 통해 소프트웨어적으로 데이터베이스를 분산처리하여 성능이 저하되는 것을 방지하고 관리를 보다 수월하게 할 수 있게 됨

목적

성능

  • 특정 DML과 Query의 성능을 향상시킴
  • 주로 대용량 Data Write환경에서 효율적
  • 특히 Full Scan에서 데이터 Access의 범위를 줄여 성능향상 가져옴
  • 많은 Insert가 있는 OLTP 시스템에서 Insert 작업을 작은 단위인 파티션들로 "분산"시켜 경합을 줄임

가용성

  • 물리적인 파티셔닝으로 인해 "전체" 데이터의 훼손 가능성이 줄어들고 데이터 가용성이 향상됨.
  • 각 분할영역(파티션)을 독립적으로 백업하고 복구할 수 있다.
  • 테이블의 파티션 단위로 Disk I/O를 분산시켜 경합을 줄이기 때문에 Update 성능을 향상시킨다.

관리 용이성

  • 큰 테이블들을 제거하여 관리를 쉽게 해준다.

장점

관리적 측면

  • 파티션 단위 백업, 추가, 삭제, 변경
  • 전체 데이터를 손실할 가능성이 줄어들어 데이터 가용성 향상
  • 파티션별로 백업 및 복구 가능
  • 파티션 단위로 I/O분산이 가능하여 Update 성능 향상

성능적 측면

  • 파티션 단위 조회 및 DML 수행
  • 데이터 전체 검색시 필요한 부분만 탐색해 성능증가
  • 즉, Full Scan에서 데이터 Access의 범위를 줄여 성능 향상 가져옴
  • 필요한 데이터만 빠르게 조회가능하기 때문에 쿼리 자체가 가벼움

단점

  • 테이블간의 조인 비용이 증가
  • 테이블과 인덱스를 별도로 파티셔닝할 수 없음
  • 테이블과 인덱스를 같이 파티셔닝 해야함

종류

  • 수평(horizontal) 파티셔닝
    • 샤딩(Sharding)과 동일한 개념
  • 수직(vertical) 파티셔닝
profile
백엔드 꿈나무 🐥

0개의 댓글