ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 3장 - 저장소와 검색
    CS/데이터 중심 애플리케이션 설계 요약 2022. 11. 17. 00:01

    DB의 내부 상황

     

    항상 주변을 단정히 정돈하는 사람은 단지 찾기를 너무 귀찮아하는 사람이다.

    DB는 대표적으로 두 가지 작업을 수행합니다.

    1. 데이터 저장

    2. 데이터 조회

     

    2장에서 여러 데이터 모델들을 알아보았고 질의 언어를 통해 조회하는 것도 알아보았습니다.

     

    데이터베이스가 데이터를 어떻게 저장하고 어떻게 조회할까요?

     

    데이터베이스가 저장과 검색을 내부적으로 처리할 때 개발자가 주의해야 하는 이유는 무엇일까요?

     

    DB를 강력하게 만드는 데이터 구조

    많은 데이터베이스는 내부적으로 추가 전용 데이터 파일인 로그를 사용합니다.

    사람이 읽을 수 있는 형식일 필요는 없으며 특정 읽기 전용 프로그램만 읽을 수 있는 바이너리여도 상관없습니다.

     

    색인

    어떤 부가적인 메타데이터를 유지하며 이정표의 역할을 하여 원하는 데이터의 위치를 찾는데 도움을 줍니다.

    색인은 DB내용에는 영향을 미치지 않으며 단순 질의 성능에만 영향을 줍니다.

    하지만 추가적인 메타데이터를 관리해야 하기 때문에 쓰기 과정에서 추가 비용이 발생합니다.

     

    따라서 읽기가 많고 쓰기가 적다면 색인을 사용하는 것이 적절할 것입니다.

    반대로 읽기가 적고 쓰기가 많다면 색인을 사용하는 것이 부적절합니다.

     

    해시 색인

    키 - 값 데이터를 통해 키-값 저장소는 우리가 흔히 아는 자료구조 hash map으로 구현합니다.

    O(1)의 시간 복잡도를 자랑하지만 범위 질의에 효율적이지 않습니다.

     

    SS 테이블과 LSM 트리

    SS테이블은 Sorted String Table의 약자로 키로 정렬된 문자열 테이블을 뜻합니다.

    red-black tree, AVL 트리와 같은 데이터 구조를 이용하면 임의 순서로 키를 삽입하고 정렬된 순서로 해당 키를 다시 읽을 수 있습니다.

     

    LSM 트리는 Log Structured Merge Tree의 약자로 로그 구조화 병합 트리를 뜻합니다.

    이 색인 구조는 로그 구조화 파일 시스템의 초기 작업의 기반이 됩니다.

     

    B 트리

    가장 널리 사용되는 색인 구조이며 로그 구조화 색인과는 상당히 다릅니다.

    1970년대에 등장하여 10년도 안돼 "보편적인 색인 구조"라 불렸습니다.

    RDB뿐만 아니라 NoSQL에서도 사용합니다.

     

    4KB 크기의 고정 크기 블록이나 페이지로 나누고 한 번의 하나의 페이지에 읽기 또는 쓰기를 합니다.

    디스크가 고정 크기 블록으로 배열되기 때문에 하드웨어와 조금 밀접한 관련이 있습니다.

     

    각 페이지는 주소나 위치를 통해 식별할 수 있습니다.

    하나의 페이지가 다른 페이지를 참조할 수 있습니다.

     

    한 페이지는 B트리의 루트로 지정되며 항상 루트에서 시작하여 키를 찾습니다.

    최종적으로는 리프 페이지(키를 포함하는 페이지)에 도달합니다.

     

    항상 균형이 유지되는 Blacned-Tree이며 n개의 키를 가진 트리는 깊이가 항상 O(log n)입니다.

     

    신뢰할 수 있는 B 트리 만들기

    DB 고장 상황에도 스스로 복구할 수 있게 하려면 일반적으로 디스크 상에 쓰기 전 로그라고 하는 데이터 구조를 추가해 B트리를 구현합니다.

    쓰기 전 로그는 트리 페이지에 변경된 내용을 적용하기 전에 모든 B 트리의 변경사항을 기록하는 추가 전용 파일입니다.

    이 로그는 DB가 고장 이후 복구될 때 일관성 있는 상태로 B 트리를 다시 복원하는 데 사용합니다.

     

    같은 자리의 페이지를 갱신하는 작업이 있으면 어떨까요?

    다중 스레드가 동시에 B 트리에 접근한다면 주의 깊게 동시성 제어를 해야 합니다.

    동시성 제어는 보통 래치(가벼운 잠금)로 트리의 데이터 구조를 보호합니다.

     

     

    색인 안에 값 저장하기

    색인에서 키는 질의가 검색하는 대상이지만 값은 다음의 두 가지 중 하나에 해당합니다.

    1. 실제 로우

    2. 다룬 곳에 저장된 로우를 가리키는 참조

     

    2번의 경우 로우가 저장된 곳을 힙 파일이라 하며 특정 순서 없이 데이터를 저장합니다.

    각 색인은 힙 파일에서 위치만 참조하고 실제 데이터는 일정한 곳에 유지합니다.

     

    이런 접근 방식은 키를 변경하지 않고 값을 갱신할 때 효율적입니다.

    새로운 값이 이전 값보다 많은 공간을 필요로 하지 않으면 레코드를 제자리에 덮어씁니다.

    반대의 경우에는 조금 복잡해집니다.

    힙에서 충분한 공간이 있는 새로운 곳으로 참조를 이동하도록 갱신해야 합니다.

     

    2번과 같이 색인에서 힙 파일로 다시 이동하는 일은 읽기 성능에 불이익이 너무 많기 때문에 색인 안에 바로 실제 로우를 저장하는 편이 좋을 수 있습니다.

     

    1번같은 경우는 클러스터드 인덱스라 합니다.

    MySQL의 InnoDB 엔진에서 테이블의 기본키는 언제나 클러스터드 인덱스이며 보조 색인은 기본키를 참조합니다.

     

    클러스터드 인덱스와 비 클러스터드 인덱스 사이의 절충안을 커버링 색인이나 index with included column이라 합니다.

    색인 안에 테이블의 칼럼 일부를 저장하여 색인만 사용하여 일부 질의에 응답이 가능합니다.

     

    모든 종류의 데이터 복제와 마찬가지로 클러스터드 인덱스, 커버링 인덱스는 읽기 성능을 높일 수 있습니다.

    하지만 추가적인 저장공간이 필요하고 쓰기 과정에 오버헤드가 발생합니다.

    또한 애플리케이션 단에서 복제로 인한 불일치를 파악할 수 없기 때문에 DB는 트랜잭션 보장을 강화하기 위해 별도의 노력이 필요합니다.

     

    다중 칼럼 색인

    지금까지의 색인은 하나의 키 값에만 대응합니다.

    다중 칼럼 색인의 가장 일반적인 유형으로 결합 색인이 존재합니다.

    결합 색인은 하나의 칼럼에 다른 칼럼을 추가하는 방식으로 하나의 키에 여러 필드를 단순히 결합합니다.

    예를 들어 (성, 이름)을 키로 전화번호를 값으로 한느 색인을 제공하는 구식 종이 전화번호부와 유사합니다.

     

    전문 검색과 퍼지 색인

    위의 색인들로는 철자가 틀린 단어와 같이 유시한 키에 대해서는 검색이 불가능합니다.

    전문 검색 엔진은 일반적으로 특정 단어를 검색할 때 해당 단어의 동의어로 질의를 확장합니다.

    특정 편집 거리 내 단어를 검색할 수 있습니다.

     

     

    모든 것을 메모리에 보관

    지금까지 설명한 데이터 구조는 모두 디스크 한계에 대한 해결책입니다.

    디스크는 전원이 꺼져도 손실되지 않으며 램보다 가격이 저렴합니다.

    하지만 램은 점점 더 저렴해지는 추세입니다.

    이런 이유는 인메모리 DB가 개발되었습니다.

     

    디스크에 변경 사항의 로그를 기록하거나 주기적으로 스냅숏을 기록하는 방식으로 지속성도 갖추고 있습니다.

     

    트랜잭션 처리나 분석

    초장기 데이터 처리는 DB 쓰기가 보통 판매, 발주, 직원 급여와 같은 상거래에 해당했습니다.

    하지만 금전 거래가 아닌 영역으로 DB가 확장되어도 트랜잭션이란 용어는 변하지 않고 논리 단위 형태로서 읽기와 쓰기 그룹을 나타냅니다.

     

    트랜잭션이 반드시 ACID 속성을 가질 필요는 없습니다.

    단지 클라이언트가 지연시간이 낮은 읽기와 쓰기를 가능하게 해야 합니다.

     

    DB가 많은 종류의 데이터(블로그, 댓글, 게임, 연락처)를 사용하기 시작했지만 기본적인 접근 패턴은 비즈니스 트랜잭션 처리와 유사합니다.

     

    DB를 데이터 분석에도 점점 더 많이 사용하기 시작했습니다.

     

    처음에는 트랜잭션 처리와 분석 질의를 동일한 DB에서 사용했습니다.

    이와 관련하여 SQL이 매우 유연한 모습을 보였습니다.

     

    하지만 트랜잭션 처리 시스템을 분석 목적으로 사용하지 않고 개별 DB에서 분석을 수행하려는 경향이 나타나기 시작했습니다.

    이런 개별 DB를 데이터 웨어하우스라고 부릅니다.

     

    데이터 웨어하우스는 트랜잭션 작업이 영향을 주지 않고 마음껏 질의할 수 있는 개별 DB입니다.

    트랜잭션 작업을 처리하는 DB 시스템의 데이터의 읽기 전용 복사본입니다.

    기존 DB로부터 주기적인 데이터 덤프나 지속적인 갱신 스트림을 통해 적재합니다.

     

    데이터 웨어하우스

    데이터 웨어하우스에 대한 자세한 설명은 다루지 않겠습니다.

     

    정리

    데이터베이스 어떻게 저장과 검색을 다루는지 근본적인 내용을 알아보았습니다.

    또한 고수준 저장소 엔진은 트랜잭션 처리 최적화와 분석 최적화라는 큰 두 가지 범주로 나뉩니다.

     

    트랜잭션 처리 시스템은 보통 사용자 대면이기 때문에 대량의 요청을 받을 수 있습니다.

    부하를 처리하기 위해 보통 애플리케이션이 각 질의마다 작은 수의 레코드만 다룹니다.

    애플리케이션은 키의 일부만 사용하는 레코드를 요청하고 저장소 엔진은 요청한 키의 데이터를 찾기 위해 색인을 사용합니다.

    이때 디스크 탐색이 병목입니다.

     

    데이터 웨어하우스와 유사한 분석 시스템은 최종 사용자가 아닌 비즈니스 분석가가 주로 이용합니다.

    트랜잭션 처리 시스템보다 더 적은 수의 질의를 다루지만 매우 다루기 어렵고 짧은 시간 시간에 수백만 개의 레코드를 스캔해야 합니다.

    따서 이때는 디스크 대역폭이 병목입니다.

     

    애플리케이션 개발자가 저장소 엔진의 내부에 대한 지식이 있다면 특정 애플리케이션에 어떤 도구가 가장 적합한지 판단하기에 유리합니다.

     

    특정 저장소 엔진을 튜닝하는 전문가가 될 수는 없지만 선택한 데이터베이스의 문서를 이해할 수 있는 충분한 어휘와 개념을 갖추는데 분명 도움이 될 것입니다.

    댓글

Designed by Tistory.