ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 컬럼 기반 저장소 와 행 기반 저장소
    elasticsearch 2021. 3. 3. 22:10
    반응형

    컬럼 기반 저장소에 대해서 알지 못했는데 es에서 field_datta, doc_value에 대해서 알아보다 컬럼 기반 저장소를 사용한다고 해서 찾아보고 정리, 번역하였다

     

     

    rdbms 저장구조

     

     

    행 기반 database에서 행 값은 대게 연속적으로 저장된다

    행 헤더는 레코드 길이, null bit 등등 포함하고 있다

     

     

    좀 더 디테일하게 보면 테이블 데이터 파일을 봤을 때 아래와 같이 이루어져 있다

    실제 행 값은 값 구조의 특정 오프셋을 저장한다

    오프셋은 컬럼 타입에 의존한다

     

    특정 행를 읽기 위해 그 첫번째 위치를 알아야 하는데 행에 존재하는 필드들이 고정 길이를 가지고 있으면 이것은 매우 쉽다

     

     

    그러나 아래 이미지와 같이 varchar와 같은 가변적인 길이라면 쉽지 않다 고정적인 길이가 아닌 가변적인 길이 때문에 다음 헤더까지 점프해서 이동 하기 어렵다

    그래서 특정 행의 시작점을 계산하기 위해 레코드 길이를 헤더에 저장해서 사용한다

    이것은 헤더들을 횡단할 수 있음을 의미한다

     

    그리고 아래와 같이 고정 값을 만들어 놓고 초과되는 부분에는 다른 곳에 저장을 하면 가변 길이에 대한 문제를 해결할 수 있다

     

     

    page와 page split

    sql server에서는 page가 8개면 1가의 extend가 된다

     

    데이터 파일은 페이지로 이루어져있다

    특정 행 데이터를 읽기 위해 페이지 전체를 읽어야 한다

    행이 작을 수록 더 페이지 안에 딱 들어 맞게 들어 갈 수 있고 페이지에 데이터가 채워지지 않는 경우도 있다 채워지지 않는 것은 나중에 해당 데이터가 업데이트 될 때 페이지 스플릿이나 이동 없이 업데이트 할 수 있다는 장점은 있지만 해당 공간을 낭비할 수 있다

     

    페이지 스플릿은 아래와 같이 데이터 페이지가 풀로 차면 분리를하게 된다

     

     

    아래와 같은 상황에서 데이터 5가 들어가게 되면 해당 페이지 공간은 다 차있기 때문에 페이지를 분할해서 저장한다 그런데 해당 작업의 비용은 꽤나 비싼 비용이기 때문에 공간을 남겨두는 경우도 있다 존재하던 데이터의 크기가 커질 수도 있고 데이터가 들어오면 스플릿을 최대한 방지하기 위함이다

     

     

    행 기반 저장소에서 오직 컬럼의 작은 양이 필요할 때 효과적이다 그러나 테이블은 컬럼을 많이 가지고 있다

    예를들면 오직 c1필드만 필요하지만 3개의 값을 얻기 위해 불필요한 데이터까지 포함해서 2개의 페이지를 읽어야한다

     

    하지만 아래와 같이 하나의 필드만 저장해 놓는 필드는 내가 원하는 필드의 데이터만 읽을 수 있다 그래서 column-oriented storage가 나오게 되었다

     

     

    컬럼 기반 저장소는 정확히 검색하려고 했던 컬럼만 읽어들임으로써 굉장히 퍼포먼스를 향상시킬 수 있다

    컬럼 기반 저장소 10기가는 각각 독립적으로 아래와 같이 저장된다

    column a: 4gb

    column b: 2gb

    column c: 3gb

    column d: 1gb

    우리가 만약 d필드를 읽는다면 1gb만 읽어들이면 되지만 행 기반 저장소에서는 10gb를 모두 읽어야 한다

     

    가장 간단한 케이스는 one datafile per coumn이다

    컬럼 기반 저장소는 행 기반 저장소에 비해 같은 I/O 리소스면 더 많은 데이터를 읽을 수 있다 이유는 행 기반 저장소는 내가 읽고 싶지 않은 필드도 읽어야 하기 때문이다

    헤더 정보를 입력하지 않는다

    각각의 컬럼 데이터 파일은 같은 타입이므로 압축을 더 효율적으로 할 수 있도록 한다

    압축률이 높아지니 I/O 발생을 좀 더 줄일 수 있다 그러나 cpu 비용은 발생한다

    메모리 크기보다 큰 데이터 세트의 경우 디스크 액세스가 압축 해제보다 느리기 때문에 종종 유용하다

    열 저장소의 압축에 대한 좋은 사용 사례는 가변 길이 문자열 값에 대한 사전 압축이다

    컬럼 추가 삭제 비용도 상대적으로 저렴하다 이유는 컬럼이 따로 존재하거나 같은 파일이라도 해당 컬럼의 값이 순차적으로 존재하기 때문이다

    컬럼에 값을 추가 하고 수정 비용은 행 저장소보다 크다 여러개의 컬럼을 한번에 수정하면 당연히 접근해야 할 곳이 많기 때문에 추가하고 수정하는데 비용이 많이 들 것 같다

     

    Columnstore 인덱스는 rowstore 인덱스보다 최고 10배 높은 데이터 압축률을 보여 준다. 이를 통해 분석 쿼리를 실행하는 데 필요한 I/O는 크게 줄이고 그에 따라 쿼리 성능이 향상된다.

    • Columnstore 인덱스는 디스크에서 압축된 데이터를 읽는다. 즉, 메모리로 읽어야 하는 데이터 바이트가 적어진다.
    • columnstore 인덱스는 데이터를 압축된 형태로 메모리에 저장한다. 이렇게 하면 동일한 데이터를 메모리로 읽는 횟수가 줄어 I/O도 줄어든다. 예를 들어 압축률이 10배인 columnstore 인덱스에서는 데이터를 압축되지 않은 형태로 저장하는 작업과 비교해 볼 때 메모리에 10배 이상의 데이터를 보관할 수 있다. 메모리에서 더 많은 데이터를 사용하면 columnstore 인덱스에서는 디스크에서 추가 읽기를 하지 않고도 메모리에 필요한 데이터를 찾을 가능성이 높다.
    • columnstore 인덱스는 행이 아니라 열을 기준으로 데이터를 압축하여 높은 압축률을 확보하고 디스크에 저장되는 데이터의 크기를 줄인다. 각 열은 개별적으로 압축되어 저장된다. 한 열에 있는 데이터는 항상 형식이 동일하며, 유사한 값을 포함하려는 경향이 있습니다. 데이터 압축 기술은 값이 비슷할 경우 더 높은 압축률을 달성할 수 있다
    • 예를 들어 팩트 테이블에 고객 주소가 저장되어 있고 국가에 대한 열이 하나 있는 경우 가능한 총 값 수는 200개 미만이다. 이러한 값 중 일부는 여러 번 반복된다. 팩트 테이블에 1억 개의 행이 있는 경우에는 국가 열이 쉽게 압축되므로 요구되는 스토리지 크기는 매우 작다. 행 단위 압축은 이 방식으로 열 값의 유사성을 활용할 수 없어 국가 열의 값을 압축하는 데 더 많은 바이트를 사용한다

     

    참조

    https://la-stranger.tistory.com/entry/columnar-database-vs-row-database

    https://slideplayer.com/slide/6022163/

    https://www.idera.com/productssolutions/sqlserver/sqldefragmanager/what-is-fragmentation

    https://docs.microsoft.com/ko-kr/sql/relational-databases/indexes/columnstore-indexes-query-performance?view=sql-server-ver15

     
    반응형

    댓글

Designed by Tistory.