[SQL 레벨업] Ch.1 DBMS 아키텍처

Manx·2022년 8월 1일
0

SQL 레벨업

목록 보기
1/11

1. DBMS 아키텍처 개요

- 쿼리 평가 엔진

입력받은 SQL을 분석하고, 어떤 순서로 기억장치의 데이터에 접근할지 결정한다.
이때 결정되는 계획을 '실행 계획'이라고 부른다.
실행 계획에 기반을 둬서 데이터에 접근하는 방법을 '접근 메서드(access method)'라고 부른다.

쿼리 평가 엔진 = 계획을 세우고 실행하는 DBMS의 핵심 기능을 담당하는 모듈

- 버퍼 매니저

DBMS는 특별한 용도로 사용하는 메모리 영역을 확보해둔다. (버퍼)
버퍼매니저가 이 메모리 영역을 관리한다.
디스크를 관리하는 디스크 용량 매니저와 함께 연동되어 작동한다.

- 디스크 용량 매니저

가장 많은 데이터를 다루는 소프트웨어
데이터베이스는 데이터를 영구적으로 저장해야 하므로 디스크 용량 매니저가 어디에 어떻게 데이터를 저장할지 관리하고, 읽고 쓰기를 제어한다.

- 트랜잭션 매니저 & 락 매니저

트랜잭션과 락을 관리한다. ( 트랜잭션과 락에 대해서는 다른 포스트에서 정리해서 설명하지 않겠다.)

- 리커버리 매니저

데이터를 정기적으로 백업하고, 문제가 일어났을 때 복구해주는 기능을 수행


2. DBMS와 버퍼

메모리는 한정된 희소 자원인 반면에 데이터는 굉장히 많기 때문에 버퍼에 어떤 식으로 확보할 것인가 하는 부분에서 트레이드오프가 발생한다.
DBMS는 대부분 용량, 비용, 성능의 관점에서 HDD를 사용한다.
성능 향상을 위해 자주 참조되는 데이터를 메모리 위에 올려둔다.
-> 성능 향상을 목적으로 데이터를 저장하는 메모리를 버퍼(buffer), 캐시(cache)라고 부른다.

버퍼에 어떻게, 어느 정도의 기간 동안 올릴지를 관리하는 것이 버퍼 매니저이다.


DBMS가 데이터를 유지하기 위해 사용하는 메모리

데이터 캐시

  • 디스크에 있는 데이터의 일부를 메모리에 유지하기 위해 사용하는 메모리 영역

로그 버퍼

  • INSERT, DELETE, UPDATE, MERGE와 같은 갱신 처리를 처리
  • 곧바로 저장소에 있는 데이터를 변경하지 않고, 로그 버퍼 위에 변경 정보를 보내고 이후에 디스크 내용 수정

갱신 처리는 SQL 실행 시점과 저장소에 갱신하는 시점에 차이가 있는 비동기 처리이다.
Why ? -> 갱신 시 상당한 시간이 소모되므로 갱신 정보를 받은 시점에 로그를 쌓고, 내부적으로 관련된 처리를 수행한다.

동기와 비동기의 트레이드오프

메모리의 휘발성때문에 로그 버퍼의 데이터가 DBMS가 다운될 때 사라지는 현상이 생길 수 있다.
이를 방지하기 위해 커밋 시점에 반드시 갱신 정보를 영속적인 저장소 위에 씀으로써, 장애가 발생해도 정합성을 유지할 수 있게 한다. ( 커밋 시 동기로 처리)

  • 비동기 처리 : 데이터 정합성 ↓, 성능 ↑
  • 동기 처리 : 데이터 정합성 ↑, 성능 ↓

데이터 캐시와 로그 버퍼의 크기

DBMS에서 제공하는 데이터 캐시에 비해 로그 버퍼의 초깃값이 굉장히 작다.
-> 데이터베이스는 기본적으로 검색을 메인으로 처리한다고 가정하기 때문이다.
검색 시에 레코드가 수천만 건에 달하는 경우도 있지만, 갱신 처리는 많아봤자 수만 건 정도밖에 안된다.

갱신 처리에 값비싼 메모리를 많이 사용하는 것보다는, 자주 검색하는 데이터를 캐시에 올려놓는 것이 더 좋은 성능을 낼 수 있다.

트레이드오프 하자
자신의 시스템에 검색보다 업데이트가 많다 : 데이터 캐시 < 로그버퍼
업데이트보다 검색이 많다 : 데이터 캐시 > 로그 버퍼

워킹 메모리

2개의 버퍼 이외에도 정렬 또는 해시 관련 처리에 사용되는 작업용 영역으로 워킹 메모리를 가지고 있다.
ORDER BY, 집합, 윈도우 함수 등의 기능을 사용할 때 실행된다.
워킹 메모리영역은 메모리 공간이 부족하면 저장소를 사용하기 때문에 속도가 저하된다.

  • 오라클 : 임시 테이블 스페이스(TEMP Tablespace)
  • MSSQL : TEMPDB
  • PostgreSQL : 일시 영역(pgsql_tmp)

3. DBMS와 실행 계획

DBMS의 쿼리 처리 흐름

1. 파서 (parser) : 사용자로부터 SQL구문이 올바른지 검사한다.

2. 옵티마이저 (optimizer)

  • 인덱스 유무, 데이터 분산 또는 편향도, 매개변수 등의 조건을 고려해 선택 가능한 많은 실행 계획을 작성한다.
  • 많은 실행 계획들의 비용을 계산한다.

3. 카탈로그 매니저 (catalog manager)

옵티마이저가 비용을 계산하는데 도움을 준다.
DBMS의 내부 정보를 모아놓은 테이블로, 테이블 또는 인덱스의 통계 정보가 저장되어 있다. -> '통계 정보' 라 칭한다.

4. 플랜 평가 (plan evaluation)

옵티마이저가 여러 개의 실행 계획을 세운 뒤 그것을 받아 최적의 실행 결과를 선택한다.

주의
플랜 선택을 옵티마이저에게 맡길 경우, 최적의 플랜이 선택되지 않을 수 있다.
대표적 이유 : 통계 정보 부족 (카탈로그 매니저)
-> 데이터의 수정이 일어났을 때 카탈로그 정보가 갱신되지 않아 과거의 정보로 선택할 수 있다.

테이블의 데이터가 많이 바뀌면 카탈로그의 정보도 업데이트 해야 하는 것이 상식이다. ( 업데이트 실행 비용이 많이 든다. )


4. SQL 구문 실행 계획

  • 테이블 풀 스캔(Full Scan) : O(n)
  • 인덱스 스캔 : O(log n)

결합의 실행 계획 알고리즘

  1. Nested Loops
    한쪽 테이블을 읽으며 레코드 하나마다 결합 조건에 맞는 레코드를 다른 쪽 테이블에서 찾는 방식 -> 이중 for문

  2. Sort Merge
    결합 키로 레코드를 정렬한 뒤, 순차적으로 두 개의 테이블을 결합하는 방법
    결합 전에 전처리로 정렬을 수행해야 한다 -> 워킹 메모리 사용

  3. Hash
    해시 테이블을 만듦 -> 작업용 메모리 영역 필요

Oracle : NESTED LOOPS
PostgerSQL : NESTED LOOPS

실행 계획은 일반적으로 트리 구조이다. 중첩 단계가 깊을수록 먼저 실행된다.

옵티마이저가 완벽하지 않기 때문에 Hint 구를 사용해 최적의 선택을 할 수 있게 수동으로 조절할 수 있다.

캐시 히트율을 올리고 싶을 때, 기본적으로 많이 사용하는 알고리즘은 LRU(Least Recently Used) 알고리즘이다.
-> 분명 블로그 어딘가에 정리되어 있다.. 어디갔지

profile
백엔드 개발자

0개의 댓글