저장소와 검색

기본적으로 데이터베이스는 데이터를 저장하고, 데이터를 제공하는 작업을 수행한다. 이 방법을 개발자가 주의해야하는 이유는 직접 저장소 엔진을 구현하기 보다는 사용 가능한 여러 저장소 엔진 중에 적합한 엔진을 선택하기 때문이다. 특정 작업부하 유형에서 좋은 성능을 내게끔 저장소 엔진을 조정하려면 내부에서 수행되는 작업에 대해 이해할 필요가 있다.

색인은 기본 데이터에서 파생된 추가적인 구조. 쓰기 속도를 느리게 만든다. 데이터를 쓸 때마다 매번 색인도 갱신해야 하기 때문. 중요한 트레이드 오프이다. 읽기는 빨라지지만 쓰기는 느려진다. 그래서 보통 자동으로 모모든 것 색인하지 않고, 관리자가 수동으로 색인을 선택하거나 만든다.

해시 색인

키-값 데이터의 경우 사전 타입과 매우 유사하다. 보통 해시 맵으로 구현한다. 각 키의 값이 자주 갱신되는 상황에 매우 적합하다.

해시 테이블은 메모리에 저장해야 하므로 키가 너무 많으면 문제가 된다. 원칙적으로는 디스크에 해시 맵을 유지할 수 있지만 성능이 안 좋다.

SS테이블(Sorted string Table) : 키로 정렬된 형식. 각 키는 세그먼트 파일 내에 한 번만 나타나야 한다.

LSM 트리(Log-Structured Merge-Tree) : 정렬된 파일 병합과, 컴팩션 원리를 기반으로 하는 저장소 엔진

루신에서 엘라스틱서치, 솔라에서 사용하는 전문 검색 색인 엔진.

최적화

SS테이블을 압축하고 병합하는 전략, 사이즈 계층(상대적으로 좀 더 새롭고 작은 SS테이블을 상대적으로 오래됐고 큰 SS테이블에 연이어 병합한다.) 레벨 컴팩션(키 범위를 더 작은 SS테이블로 나누고 오래된 데이터는 개별 “레벨”로 이동하기 때문에 컴팩션을 점진적으로 진행 디스크 공간을 덜 사용)

LSM트리의 기본 개념은 연쇄적으로 SS테이블을 지속적으로 병합하는 것.

B트리

루트로 시작해서 개별 키를 포함하는 페이지에 도달 -> 값을 포함하거나 값을 찾을 수 있는 페이지의 참조를 포함(row id). 트리가 계속 균형을 유지하는 것을 보장한다. 대부분의 데이터베이스는 B트리의 깊이가 3~4단계 정도면 충분하다.

신뢰성 : 다중 스레드가 동시에 B트리에 접근한다면 동시성 제어를 해야한다. 스레드가 일관성이 깨진 상태의 트리에 접근. 보통 래치(latch)로 트리의 데이터 구조를 보호한다.

페이지에 전체 키를 저장하는 게 아니라 키를 축약해 쓰면 공간을 정략, -> 트리 깊이 수준을 낮출 수 있다. B+tree. LSM트리는 보통 쓰기에서 빠른 반면, B트리는 읽기에서 더 빠르다고 여긴다.

+ 클러스티드 인덱스( 인덱스에 바로 데이터를 저장한다) + 커버링 인덱스( 일부 데이터만 저장한다)

-> 읽기 성능은 높이지만 쓰기 과정에 오버헤드가 생긴다.

모든 것을 메모리에 보관

램이 저렴 해져서 메모리에 전체를 보관하는 방식인 인메모리 데이터베이스가 개발. 디스크에 주기적인 스냅샷을 기록하거나 다른 장비에 인메모리 상태를 복제하는 방법을 사용해서 데이터 손실을 막는다. 기록은 단순히 지속성을 위한 추가 전용 로그로 사용한다.

레디스나 카우치베이스는 비동기로 디스크에 기록하기 때문에 약한 지속성을 제공한다.

근대 무조건 디스크기반 저장소 엔진이 나쁜 건 아님, 운영체제가 최근에 사용한 블록을 메모리에 캐시하기 때문에 충분한 메모리를 가진 경우에는 디스크 접근 안함. 오히려 기록해야 하는 오버헤드를 피할 수 있어서 더 빠를 수도 있다.

안티 캐싱 접근방식은 메모리가 충분하지 않을 때 가장 최근에 사용하지 않은 데이터를 메모리에서 디스크로 내보내고 나중에 다시 적재하는 방식 -> OS에서 가상메모리와 스왑 파일에서 수행하는 방식이랑 비슷하지만 DB는 전체 메모리 페이지보다 개별 레코드 단위로 작업할 수 있기 때문에 OS보다 효율적으로 관리 가능.

트랙잭션 처리 분석

보통 애플리케이션은 색인을 사용해 일부 키에 대한 적은 수의 레코드를 찾는다. 레코드는 사용자 입력을 기반으로 삽입되거나 갱신된다. 대화식이기 때문에 온라인 트랜잭션처리(OLTP)라 한다.

데이터 분석에도 점점 더 많이 사용하기 시작했는데 트랜잭션과 접근 패턴이 매우 다르다. 많은 수의 레코드를 스캔해 레코드당 일부 칼럼만 읽어 집계 통계를 계산해야 한다. 이런 사용패턴을 온라인 분석처리 (OLAP)라고 한다.

SQL이 매우 유연한 모습을 나타냈다. 분석을 위한 개별 데이터베이스를 데이터 웨어하우스라고 부른다.

데이터 웨어하우징

OLTP시스템은 일반적으로 높은 가용성과 낮은 지연 시간의 트랙잭션 처리를 기대한다. 그래서 관리자는 철저하게 보호하려 한다. 분석을 위해 OLTP시스템에 직접 질의하지 않고 개별 데이터 웨어하우스를 사용하는 큰 장점은 분석 접근 패턴에 맞게 최적화할 수 있다는 점이다. 색인 알고리즘은 OLTP에서 잘 동작하지만 분석 질의의 응답에서는 별로 좋지 않은 편이다.

OLTP 데이터베이스와 데이터 웨어하우스의 차이점:

SQL 질의를 생성하고 결과를 시각화하고 분석가가 데이터를 탐색할 수 있게 해주는 분석 도구가 있다.

표면적으로 비슷해 보이지만, 각각 매우 다른 질의 패턴에 맞게 최적화됐기 때문에 시스템의 내부는 완전히 다르다.

분석용 스키마 : 별 모양 스키마와 눈꽃송이 모양 스키마.

별 모양 스키마는 테이블 관계가 시각화 될 때 사실 테이블이 가운데에 있고 차원 테이블로 둘러싸고 있다는 사실, 이거의 변형이 눈꽃송이 모양 스키마. 차원이 하위차원으로 더 세분화된다. 더 정규화 됐다.

칼럼 지향 저장소

사실 테이블에는 대개 100개 이상의 칼럼, 수백 개인 경우도 있다. 분석과 관련된 모든 메타데이터를 포함하므로 폭이 매우 넓다.

대부분의 OLTP 데이터베이스 저장소는 로우 지향방식으로 데이터를 배치한다. 칼럼 지향 저장소는 모든 값을 하나의 로우에 저장하지 않고 각 칼럼별로 모든 값을 함께 저장한다. 질의에 사용되는 칼럼만 읽고 구분 분석하면 된다.

칼럼 지향 저장소는 대게 압축에 적합하다. 보통 칼럼에서 고유 값의 수가 로우 수에 비해 적으면 비트맵 인덱스를 사용한다. 이거는 데이터 웨어하우스에서 일반적으로 사용되는 질의 종류에 매우 적합하다.

디스크로부터 메모리로 데이터를 가져오는 대역폭이 큰 병목. CPU명령 처리 파이프라인에서 분기예측 실패를 피하며 SIMD명령을 사용하게끔 신경 써야한다. L1캐시에 딱 맞게 덩어리로 나누어 가져오는 방법. 칼럼 압축을 사용해서 덩어리를 바로 연산할 수 있게 설계한 기법을 벡터화 처리.

데이터 큐브와 구체화 뷰

동일한 집계를 많은 다양한 질의에서 사용한다면 매번 원시 데이터를 처리하는 일은 낭비다. 많이 사용되는 count, sum을 캐시하는 건 어렵지 않다. -> 구체화 뷰. 원본 데이터를 변경하면 구체화 뷰를 갱신해야 한다. 비정규화된 복사본이기 때문이다. 이런 갱신으로 인한 쓰기는 비용이 비싸기 때문에 OLTP에서는 자주 사용하지 않는다. OLAP, 데이터 큐브라고 알려진 구체화 뷰는 그 사례. 구체화 데이터 큐브의 장점은 특정 질의를 효과적으로 미리 계산했기 때문에 해당 질의를 수행할 때 매우 빠르다. 단점은 유연성이 없다는 점.

정리

고수준에서 저장소 엔진은 트랜잭션 처리 최적화(OLTP)와 분석 최적화(OLAP)라는 범주로 나뉜다.

OLTP:사용자 대면, 대량의 요청을 받고 작은 수의 레코드만 다루며 색인을 사용, 디스크 탐색이 주요 병목

OLAP”비즈니스 분석가가 주로 사용, 적은 수의 질의를 다루지만 레코드의 수가 많다. 디스크 대역폭이 병목

OLTP측면 두가지 관점

로그 구조화 관점: 파일에 추가와 오래된 파일의 삭제만 허용. 한번 쓰여진 파일은 절대 갱신 X 제자리 갱신 관점 : 덮어쓰기 할 수 있는 고정 크기 페이지의 셋으로 디스크를 다룬다.

B tree OLTP는 좀 더 복잡한 색인 구조와 모든 데이터를 메모리에 유지하기 위해 최적화된 데이터베이스를 사용

Last updated