입력받은 SQL을 분석하고, 어떤 순서로 기억장치의 데이터에 접근할지 결정한다.
이때 결정되는 계획을 '실행 계획'이라고 부른다.
실행 계획에 기반을 둬서 데이터에 접근하는 방법을 '접근 메서드(access method)'라고 부른다.
쿼리 평가 엔진 = 계획을 세우고 실행하는 DBMS의 핵심 기능을 담당하는 모듈
DBMS는 특별한 용도로 사용하는 메모리 영역을 확보해둔다. (버퍼)
버퍼매니저가 이 메모리 영역을 관리한다.
디스크를 관리하는 디스크 용량 매니저와 함께 연동되어 작동한다.
가장 많은 데이터를 다루는 소프트웨어
데이터베이스는 데이터를 영구적으로 저장해야 하므로 디스크 용량 매니저가 어디에 어떻게 데이터를 저장할지 관리하고, 읽고 쓰기를 제어한다.
트랜잭션과 락을 관리한다. ( 트랜잭션과 락에 대해서는 다른 포스트에서 정리해서 설명하지 않겠다.)
데이터를 정기적으로 백업하고, 문제가 일어났을 때 복구해주는 기능을 수행
메모리는 한정된 희소 자원인 반면에 데이터는 굉장히 많기 때문에 버퍼에 어떤 식으로 확보할 것인가 하는 부분에서 트레이드오프가 발생한다.
DBMS는 대부분 용량, 비용, 성능의 관점에서 HDD를 사용한다.
성능 향상을 위해 자주 참조되는 데이터를 메모리 위에 올려둔다.
-> 성능 향상을 목적으로 데이터를 저장하는 메모리를 버퍼(buffer), 캐시(cache)라고 부른다.
버퍼에 어떻게, 어느 정도의 기간 동안 올릴지를 관리하는 것이 버퍼 매니저이다.
데이터 캐시
로그 버퍼
갱신 처리는 SQL 실행 시점과 저장소에 갱신하는 시점에 차이가 있는 비동기 처리이다.
Why ? -> 갱신 시 상당한 시간이 소모되므로 갱신 정보를 받은 시점에 로그를 쌓고, 내부적으로 관련된 처리를 수행한다.
메모리의 휘발성때문에 로그 버퍼의 데이터가 DBMS가 다운될 때 사라지는 현상이 생길 수 있다.
이를 방지하기 위해 커밋 시점에 반드시 갱신 정보를 영속적인 저장소 위에 씀으로써, 장애가 발생해도 정합성을 유지할 수 있게 한다. ( 커밋 시 동기로 처리)
- 비동기 처리 : 데이터 정합성 ↓, 성능 ↑
- 동기 처리 : 데이터 정합성 ↑, 성능 ↓
DBMS에서 제공하는 데이터 캐시에 비해 로그 버퍼의 초깃값이 굉장히 작다.
-> 데이터베이스는 기본적으로 검색을 메인으로 처리한다고 가정하기 때문이다.
검색 시에 레코드가 수천만 건에 달하는 경우도 있지만, 갱신 처리는 많아봤자 수만 건 정도밖에 안된다.
갱신 처리에 값비싼 메모리를 많이 사용하는 것보다는, 자주 검색하는 데이터를 캐시에 올려놓는 것이 더 좋은 성능을 낼 수 있다.
트레이드오프 하자
자신의 시스템에 검색보다 업데이트가 많다 : 데이터 캐시 < 로그버퍼
업데이트보다 검색이 많다 : 데이터 캐시 > 로그 버퍼
2개의 버퍼 이외에도 정렬 또는 해시 관련 처리에 사용되는 작업용 영역으로 워킹 메모리를 가지고 있다.
ORDER BY, 집합, 윈도우 함수 등의 기능을 사용할 때 실행된다.
워킹 메모리영역은 메모리 공간이 부족하면 저장소를 사용하기 때문에 속도가 저하된다.
DBMS의 쿼리 처리 흐름
옵티마이저가 비용을 계산하는데 도움을 준다.
DBMS의 내부 정보를 모아놓은 테이블로, 테이블 또는 인덱스의 통계 정보가 저장되어 있다. -> '통계 정보' 라 칭한다.
옵티마이저가 여러 개의 실행 계획을 세운 뒤 그것을 받아 최적의 실행 결과를 선택한다.
주의
플랜 선택을 옵티마이저에게 맡길 경우, 최적의 플랜이 선택되지 않을 수 있다.
대표적 이유 : 통계 정보 부족 (카탈로그 매니저)
-> 데이터의 수정이 일어났을 때 카탈로그 정보가 갱신되지 않아 과거의 정보로 선택할 수 있다.
테이블의 데이터가 많이 바뀌면 카탈로그의 정보도 업데이트 해야 하는 것이 상식이다. ( 업데이트 실행 비용이 많이 든다. )
결합의 실행 계획 알고리즘
Nested Loops
한쪽 테이블을 읽으며 레코드 하나마다 결합 조건에 맞는 레코드를 다른 쪽 테이블에서 찾는 방식 -> 이중 for문
Sort Merge
결합 키로 레코드를 정렬한 뒤, 순차적으로 두 개의 테이블을 결합하는 방법
결합 전에 전처리로 정렬을 수행해야 한다 -> 워킹 메모리 사용
Hash
해시 테이블을 만듦 -> 작업용 메모리 영역 필요
Oracle : NESTED LOOPS
PostgerSQL : NESTED LOOPS
실행 계획은 일반적으로 트리 구조이다. 중첩 단계가 깊을수록 먼저 실행된다.
옵티마이저가 완벽하지 않기 때문에 Hint 구를 사용해 최적의 선택을 할 수 있게 수동으로 조절할 수 있다.
캐시 히트율을 올리고 싶을 때, 기본적으로 많이 사용하는 알고리즘은 LRU(Least Recently Used) 알고리즘이다.
-> 분명 블로그 어딘가에 정리되어 있다.. 어디갔지