Cassandra Data Modeling Best Practices, Part 2

By | 2014-11-10

앞의 글 “Cassandra Data Modeling Best Practices, Part 1“에 이어 Part 2 번역글 입니다.

들어가기전


원문 : http://www.ebaytechblog.com/2012/08/14/cassandra-data-modeling-best-practices-part-2/

지난 번(Cassandra Data Modeling Best Practices, Part 1)에 이어 Best Practices Part 2에서는 Cassandra 특성에 기반한 설계를 중점적으로 다루고 있으며, 다음과 같이 요약할 수 있습니다.

    • Cassandra column name은 물리적으로 정렬되어 저장되는 특징이 있으며, 이를 잘 활용한다면 범위검색 시 이점이 있음.
    • Wide rows를 사용하면 그룹화된 데이터를 단 한번의 조회로 엑세스 가능 (단, 요청된 데이터는 메모리에 적재 되기 때문에 하나의 row에 대한 사이즈 조절이 중요함)
    • Row 하나는 물리적으로 분리되어 저장될 수 없기 때문에 너무 큰 사이즈는 병목의 원인이 될 수 있음.(클러스터간 하나의 row를 분리하여 저장할 수 없음.)
    • Key 선택은  네트웍 트래픽을 효율적 분산을 위해 중요함.
    • 수퍼컬럼은 2차 인덱스 사용이 어려우며, 복합컬럼의 사용이 나은 선택.
    • 특징과 용도 및 목적에 맞게 사용하여 속도와 성능에 주의 (counter column family(CF)의 대체키 사용)
    • 데이터 생성 및 업데이트 가능여부 고려하여 적용
    • 멱등형(동일한 결과값이 나오는) 구조로 설계가 필요하며, 멱등형 구조가 수용할 수 없는 기능의 경우 counter column family 와 같은 대체 기능 활용 방안 추천 내용별로 Cassandra의 특성을 고려하여 어떻게 하면 효율적인 설계가 가능한지 적절한 예를 들어 설명 하고 있습니다.

Cassandra를 사용 하지 않더라도 분산형 데이터베이스들은 유사한 특징을 지니고 있어 다른 데이터베이스 설계 시에도 도움이 될 것이라 예상됩니다.

Cassandra Data Modeling Best Practices, Part 2


 in Data Infrastructure and Services

 Part1에서, Cassandra 초기 데이터 모델링 시 도움이 될 만한 몇 가지 기초적인 사례를 예제와 함께 살펴 보았습니다.

Part1을 무시해도 상관 없지만, Part2 용어와 규칙들을 이해하기 위해서라도 간략하게 읽어보길 권고 합니다.( 만약 Cassandra가 처음이라면 part1을 읽어보길 바랍니다.)

예제 중 일부는 차후에 좀더 다루어질 예정이며, Jira를 통해 진행 상황을 확인하실 수 있습니다.

아래는 주제별로 요약된 내용입니다.

    • 데이터 저장 시 column name을 사용하라
    • ordering, grouping, and filtering 을 위해 적절히 wide rows를 사용하라
    • 적합한 (로우키)샤드키를 선택하라
    • 트래픽에 따라 데이터를 분리하라
    • 컬럼키와 로우키가 유니크인지 확인하라
    • 적절한 비교와 유효성 검사를 사용하라
    • 컬럼명을 짧게 유지해라
    • 멱등 형태로 데이터 모델을 디자인하라
    • 트랜젝션을 고려하여 데이타를 설계하라
    • front 에서 적합한 TTL을 셋팅하라
    • 대리 키를 생성하기 위해 카운터 컬럼 페밀리를 사용하지 마라
    • 수퍼컬럼 보다는 복합컬럼을 선호하라
    • 복합 컬럼 내의 서브 컬럼의 정렬 기법을 활용하라
    • 매뉴얼 구조 보다는 built-in 복합 타입을 선호하라
    • 동적 구조 보다 정적인 복합 타입을 사용하라

Storing values in column names is perfectly OK


Cassandra에 실 데이터 저장을 column value 가 아닌 column name 를 사용하여 저장할 수 있으며, null 을 허용합니다. 이러한 방식을 사용한 주된 이유는 column name기반의 물리적인 정렬 저장이 가능하지만 column value는 이러한 정렬 저장을 지원이 것이 불가능하기 때문입니다.

 Notes:

    • column key는 최대 64KB까지 사용 가능하지만, 아이템 설명과 같은 형태는 column key로 사용하지 않기를 바랍니다.
    • timestamp 는 서버간 쓰기 시에 충돌의 우려가 있으니 timeuuid를 사용을 권장합니다.
    • column value의 최대 사이즈는 2GB 지원하지만, 스트리밍 구조는 수용할 수 없으며, 요청될 때 힙메모리로 올라가니 되도록 몇 메가 사이즈로 제한해서 사용하시길 바랍니다.
      (대용량 사이즈는 아직 지원될 예정이 없다고 합니다.  Astyanax 클라이언트 라이브러리를 사용하면 지원 가능)

Leverage wide rows for ordering, grouping, and filtering


정렬, 그룹, 필터 기능을 위해 적절한 wide rows를 사용하되, 지나칠 정도로 사용은 피하는 게 좋습니다.

이전 내용을 바탕으로 계속 설명하자면, 실 데이터가 컬럼명에 저장 될 때 wide rows 사용하게 됐습니다.

Benefits of wide rows:

    • 물리적 정렬을 지원하는 컬럼명 기반으로, wide rows 사용시 그 속성을 그대로 사용 가능하며, 정렬된 데이터 특성상 효율적인 필터링이 가능하고(범위 조회) 각각의 컬럼들에 대해 효율적인 조회가 가능합니다.
    • 만약 조회된 데이터 수가 많을 시, 효율적으로 재 읽기가 가능한 하나의 wide row를 사용해 한번의 조회로 그룹화 할 수 있습니다.
    • 하나의 예로, 시계열 데이터에 대한 추적 또는 모니터링을 위해 시간/날짜/서버/이벤트 타입을 하나의 wide rows를 사용하여 그룹형태로 처리 가능합니다.
    • 하나의 row를 (나중에 논의될) 수퍼컬럼 또는 복합컬럼을 기반으로 생성시 좀 더 그룹화된 형태도 가능합니다.
    • Cassandra에서 wide rows Column family(CF)은 (복합컬럼과 같이) 인덱스를 생성하기 위해 많이 사용됩니다.
    • 덤으로, 하나의 wide rows는 데이터 중복을 피해 1:N 관계의 비정규화를 표현할 수 있습니다.
      하지만 읽기에 대한 퍼포먼스 튜닝이 필요하면서 데이터가 함께 조회될 시만 사용하시길 추천 합니다.

Example:
어떤 이벤트 로그 데이터를 저장하고 매시간 단위로 검색 된다고 가정해봅시다.

로우키가 그날의 시간으로 구성된 아래 예제에서 컬럼명은 이벤트가 일어난 시간으로 구성되고 컬럼값은 payload를 저장합니다.

염두해야 할 사항은, row는 넓고 이벤트 컬럼명은 정렬 저장속성에 의해 시간 기준으로 정렬되 있는다는 점입니다.

wide rows 단위(이 예제에서, 몇분 단위보단 시간당)는 사용된 케이스, 트레픽, 데이타 사이즈에 의존적이며, 이 부분은 나중에 다시 논의하도록 하겠습니다.

12

하나의 row 노드들간 분리되어 저장될  없기 때문에 너무 크지 않도록 조절이 필요합니다:

어느 정도의 길이가 wide row로 정의될 수 있는지 각 케이스마다 다르기 때문에 명확히 정의하는 것은 어렵습니다. 그렇지만 몇 가지 조언을 하자면:

Traffic: 모든 트래픽은 어떤 하나의 노드 또는 샤드(정확하게 말하면 하나의 리플리카 셋)로 구성된 어떤 하나의 row와 관련 되어 있습니다.

 “fat” 한 row 는 클러스터 내부에서 병목을 유발 할 수 있으며, wide row를 하나로 조합시 row 수가 클러스터 사이즈 보다 작거나,  일부 row들이 다른 곳에 비해 비대해질 때 역시 병목이 발생할 수 있습니다.

그래서 클러스터간 로드 밸런싱은 어떤 로우키를 선택하는가가 중요합니다.

다르게 말하면, 로우키는 하나의 row에 대한 범위를 정의하면서 로드 밸런싱은 디자인 시 지속적으로 염두해 두어야 합니다.

Size: 하나의 row는 노드간 공유가 불가능 하기 때문에, 하나의 row에 저장되는 데이터는 클러스터 내에 존재 하나의 노드 디스크에 맞게 저장 되어야 합니다.

그러나, 메모리에 충분히 수용될 수 없을 만큼 클 가능성이 있으며, Cassandra는 2십억건의 컬럼을 하나의 row에 수용할 수 있습니다.

ebay는 “wide rows”에 대한 벤치마킹을 진행한 적이 없지만, 하나의 row안에 몇 메가바이트 또는 몇 백만 건의 컬럼 이상으로 구성되지 않게 설계했기 때문입니다.

(로우키를 granularity하게 변화하거나, 여러 개로 분리하였습니다), 여기에 대해 흥미가 있다면, Aaron Morton가 작성한 Cassandra Query Plans 에서 wide rows와 관련된 퍼포먼스 자료를 확인하실 수 있습니다.

유의할 점은 wide rows를 사용하지 말란 의미가 아니라. 비대한 wide row를 사용하지 말란 의미 입니다.

Choose the proper row key – it’s your “shard key”


그렇지 않으면RandomPartitioner 사용할지라도 결국 병목이 발생할 것이다.

시계열 형태의 이벤트 로그를 저장하고 한 시간 주기로 조회하는 상단의 예제를 검토해보면, 한 row에 한 시간의 데이터를 함께 다루기 위한 row 키를 하나 선택했지만 문제가 있습니다.

모든 쓰기가 현재 시간 기준으로 하나의 노드에 존재하는 한 row에 해당한하면, 이는 클러스터 병목의 원인이 됩니다.

시간에서 분으로 단위를 줄이는게 과연 도움이 될까?. 어떻게 하더라도 단지 하나의 노드만 응답할 것이며 병목시점과 위치만 이동 할 뿐입니다.

Bad row key:  “ddmmyyhh”
이 문제를 해결하기 위한 한가지 방법은 로우키에 확장하는 방법이다. 이벤트 타입, 서버아이피등이 추가 될 수 있습니다.

Better row key: “ddmmyyhh|eventtype”

21

알아야 될 사항은 컬럼 패밀리 안에 존재하는 모든 이벤트 타입에 대해 글로벌 타임 형태로 정렬되어 있지않다는 사실입니다.

그러나, 추후 이벤트 타입에 의해 데이타가 그룹화 되어 보여진다면 문제되지 않을 수도 있으며, 시간순으로 정렬된 모든 이벤트에 대한 검색이 필요한 케이스라면,

해당 시간 동안 모든 이벤트 타입을 동시에 처리해야 하며, 어플리케이션 내에서 병합될 때 시간 순서대로 정렬해야 합니다.

만약 로우키에 어떤 데이타 추가가 불가능 하거나, 시간을 꼭 로우키로 사용해야 한다면, 또 다른 옵션은 로우키를 분리하여 물리적으로 분할하는 것입니다.

 “ddmmyyhh | 1″, “ddmmyyhh | 2″,… “ddmmyyhh | n”, 여기서 n은 클러스터에 존재하는 노드의 갯수입니다.

한 시간 동안 데이터를, 각 샤드에 골고루 분배하는 것이다.; 그리고 이를 위해 라운드 로빈 알고리즘이 필요합니다.

그렇지만, 한시간 동안 데이타를 읽는 것은 모든 분리된 노드들에 대해 다중 입력이 필요하며, 어플리케이션 내에서 병합작업을 수행해야 합니다.

 (여기에 랜덤 파티셔너가 사용된다는 가정이 필요하며, 따라서 로우키 기반의 범위 검색은 처리할 수 없게 된다.)

Keep read-heavy data separate from write-heavy data


이방법은. Cassandra 로우 케시에 대한 heap off 형태만이 적용 가능합니다.

케싱,NoSQL 과 관계없이 서로 다른 확장 형태를 취하는 많은 읽기와 쓰기가 필요한 데이타를 분리하는 것이 적절하다고 생각 합니다.

Notes:

    • 로우 케시는 사이즈가 일치할 때는 적합하지만, 모든 로우를 메모리에 적재하기 때문에 현재 wide row에는 맞지 않습니다.
      Cassandra-1956 와 Cassandra-2864에서 추후 릴리즈된 기능 변화 확인이 가능하지만  과도한 데이타 쓰기와 읽기에 대한 분리 저장 정책은 유효할 것입니다.
    • 하나의 컬럼 패밀리가 메모리에 적재할 수 있는 양보다 많을 지라도 그 중 자주 사용될만한 부분을 분리하여 메모리에 적재가 가능합니다.

Make sure column key and row key are unique


만약 그렇지 않다면데이타는 손실될 우려가 존재한다.

    • Cassandra(분산 데이터 베이스)는 로우키나 column key에 대해 유니크 사용이 필수가 아닙니다.
    • 역시, 분리 업데이트 기능이 존재 하질 않는다. Cassandra 에서는 항상 덮어씌우는 방식을 취합니다.
    • 만약 사고로 존재하는 로우키, column key에 대해 데이터를 insert 한다면, 기존의 컬럼 값은 어떠한 에러나 버전관리 없이 사라질 것입니다.

Use the proper comparator and validator


기본적인 BytesType 비교자(comparator) 유효성 검사자를 사용하지 마라

Cassandra 에서는 컬럼밸류를 위한 데이터 타입이 유효성 검사기라 불리며, 컬럼 명에 대한 데이터 타입은 비교자(comparator)라고 합니다.

비록 Cassandra에서 양쪽 다 필요하지 않거나, 컬럼 패밀리가 정적이거나 , 정렬 조차 사용하지 않는다고 해도, 비교자(comparator)는 필수로 정의되어야 합니다.

    • 부적절한 비교자(comparator)는 디스크 상에 컬럼명 기반으로 부적절하게 정렬할 것이며, 차후 컬럼명 기반의 범위 검색에 대해 나쁜 영향을 미칠 것입니다.
    • 한번 정의된 데이터는 모든 데이타를 재적하지 않는 한 비교자(comparator)를 변환할 수 없으며 검증자(validator)는 추후에도 변환이 가능합니다.
      comparators and validators 지원하는 데이터 타입을 Cassandra 문서를 통해 확인해보길 바랍니다.

Keep the column name short


컬럼명은 반복적으로 저장 되기 때문에 가능한 짧은 형태가 최적화에 도움이 된다.

컬럼명에 실제 데이터를 적재하는 부분은 제외하고 컬럼 값과 반복적으로 함께 저장되기 때문에 컬럼명을 짧게 유지해야 합니다.

메모리와 디스크에 대한 오버헤드는 컬럼 값보다 컬럼명이 더 클때 눈에 띄게 늘어날 것이며 작을 경우에도 마찬가지입니다.

예를 들어 설명하면 다음과 같은 케이스입니다.

ex)‘firstname’ 보다는 ‘fname’ , ‘lastname’ 보다는 ‘lname’

Note: Cassandra-4175

Design the data model such that operations are idempotent


유즈케이스가 부정확한 형태로 진행되는  또는 부정확 부분이 차후 수정이 가능한지 확인하라

Cassandra와 같은 eventually consistent 모델을 수용하는 분산 시스템은, 멱등(연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질) 기능을 많은 부분에서 지원합니다.

멱등 기능은 시스템 내에서 부분 실패를 수용하며, 시스템의 최종 상태에 대한 변화 없이 안전하게 재수행할 수 있으며, 이러한 원칙이 어떻게 Cassandra에 적용되는 지 알아 보도록 합니다.

여기서 몇 개의 부분 실패 케이스를 확인해보고, 그리고 각 케이스 별로 다양하기 때문에 다음 포스트까지 strong consistency에 대한 필요성 부분을 무시할 것입니다.
관계형 데이터베이스와 다른 Cassandra의 멀티마스터 분산 시스템의 기본 성질로 인해, 쓰기 실패는 데이터에 대한 쓰기 성공을 보장하지 않지만, 다른 말로 풀어 쓰면, 클라이언트가 쓰기 기능에 대한 실패 메시지를 받게 될 경우라도, 데이타는 리플리카셋 중 하나에 쓰여질 가능 성이 있다, 따라서 결국 리플리카셋 모두에 적용될 것이다.

Notes:

    • “멱등 업데이트” 동작이 멱등 구조의 데이터 모델이라는 의미이다. 한번이든 여러 번이든 같은 결과를 가져온다면 멱등이라고 할 수 있습니다.

대부분의 케이스에서, 항상 멱등 형태의 업데이트의 정규컬럼 패밀리에 쓰기로 인해 문제는 없습니다.

예외는 카운터 컬럼 패밀리와 같이 사용될때 발생하며, 아래 예제를 통해 확인할 수 있으며, 때로는 유즈케이스 관점에서 멱등형 업데이트 형태가 아닌 쓰기 동작의 데이타 모델이 가능합니다.

예를 들어, 파트1의 ‘사용자가 아이템을 좋아한다는’ 유즈케이스를 중복으로 수행한다고 해도, 최종모델인 User_by_Item 과 Item_by_User 멱등형 업데이트가 아니며, 매번 다른 timestamp로 업데이트 될 것입니다.

그러나, 기억해야 할 점은, ‘user likes item’ 과 같은 정해진 유즈케이스 수행은 멱등으로 분리할 수 있으며, 그래서 실패시 몇번이고 반복해서 수행할 수 있습니다.

좀더 유즈케이스를 정리하는 부분은 추후 다른 포스트에서 언급할 예정입니다.

    • consistency level ONE 일지라도, 쓰기 실패는 쓰기가 완료된 데이타를 보장하지 않습니다:
      결국 모든 리플리카에 대해 데이터를 지속적으로 전파할 것입니다.

Example
어떤 아이템을 좋아하는 사용자의 수를 조회한다고 가정해봅시다.

Cassandra의 카운터 컬럼 패밀리를 사용하여 아이템당 사용자 수를 파악하는 방법이 있습니다.

카운터 증가는 멱등형 업데이트가 아니기 때문에, 적어도 한 노드에서 카운터 증가가 성공했다면, 오버 카운트는 수행되지 않을 것입니다.

멱등형 업데이트를 만드는 또 한가지 방법은 유저의 아이디 리스트를 유지하는 방법인데, 아래와 같이 카운터를 증가시키는 방법이 있습니다.

31

유저가 아이템을 like 할 때마다, 아이템에 대해 위 멱등 모델의 업데이트는, 카운터 값을 가져오는 것은 모든 유저의 아이디를 읽어야만 가능하며 데이터 건수(몇백만)로 인해 원활히 수행되기는 어려운 상황입니다.

많은 양적 부담으로 인해 읽기 수행이 어렵고 정확한 수치가 필요하지 않다면, 카운터 컬럼은 위의 케이스에 적합하다고 볼 수 있습니다.

필요하다면 카운터 값은 컬럼 패밀리의 멱등 업데이트로부터 유저 아이디에 대한 카운팅 방식을 주기적으로 수행함으로써 정확한 값을 유지 할 수 있습니다.

Note: Cassandra-2495 하나의 실패한 요청의 경우 카운터를 위한 적합한 재수행 메커니즘의 추가가 가능하나 일반적으로, 이 예제에서는 성공을 지속적으로 유지할 것입니다.

그래서 멱등 업데이트를 위한 당신의 설계 모델에 대해 항상 리트머스 테스트 수행으로 확인할 것입니다.

*멱등에 대한 보충설명:멱등법칙 또는 멱등성(idempotence)은 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로써, 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다. 멱등법칙의 개념은 추상대수학(특히, 투영 이론·닫힘 연산·함수형 프로그래밍의 참조 투명성과 연관된 성질에서)의 여러 부분에서 사용하고 있다.

Model data around transactions, if needed


그렇지만 항상 가능하지는 안으며케이스 별로 상황이 다르다.

Cassandra는 멀티로우 방식이 아니며, 클러스터간 트랜젝션 또는 롤백 메커니즘이 없는 대신;로레벨 차원의 원자성을 제공합니다. 다른 말로 표현하면, 주어질 로우키에 연관된 컬럼에 대한 데이터 업데이트는 원자적 특징이 존재합니다.

만약 트랜젝셔널한 기능이 필요하다면, 하나의 row기반으로 즉시 업데이트 가능하도록 설계해야 됩니다.

그러나, 상황 별로 다를 수 있으며, 항상 수행하는것은 불가능합니다.

비슷한 케이스로, ACID 트렌젝션 지원이 필요한 시스템 이라면 데이타 베이스 선택에 대한 문제를 신중히 고려해야만 합니다.
Note: Cassandra-4285는 eventually consistent 배치 기능의, 원자성을 추가를 고려하고 있습니다.

Decide on the proper TTL up front, if you can


기존에 데이터에 TTL 값을 변화하긴 어렵기 때문이다.

Cassandra에서, TTL (time to live)은 정의되지 않았거나, 또는 모든 컬럼 패밀리에 적용되어 있습니다. 각 컬럼값에 셋팅되어 있으며, 셋팅 후 변경은 어렵습니다;

초기에 셋팅되어 있지 않을 시, 기존의 데이터에 추가적으로 수정 하는 것 역시 불가능 합니다. TTL 값을 갱신하기 위한 유일한 방법은 새로운 TTL 값과 함께 모든 데이타를 다시 읽고 쓰는 방법 뿐입니다.

그렇기 때문에 원래 목적을 잘 생각해보고, 가능하다면 사전에 적합한 값을 셋팅하길 바랍니다.

Note: Cassandra-3974 에서 컬럼 TTL과는 별개로 컬럼 패밀리를 위한 TTL을 확인할 수 있습니다.

Don’t use the Counter column family to generate surrogate keys


목적에 맞지 않기 때문이다.

카운터 컬럼 패밀리는 분산 카운팅을 위해 분산된 형태의 카운터들을 관리합니다. 컬럼 패밀리를 대체키 형태의 순차적 숫자(Oracle 시퀀스 와 MySQL 자동증가 컬럼과 같은 기능을 하는)들로 생성하여 사용하는 것은 자제하시기 바랍니다.

사용하게 된다면 중첩된 형태의 시퀀스 숫자를 할당 받을 것입니다. 대부분 시스템에서 전체를 위한 시퀀스 발급은 필요한 경우가 드물다고 볼 수 있습니다.

그리고 필요 시 timeuuid가 대체키로 더 적합하다 볼 수 있습니다. 정말 전체 시퀀스 생성이 필요하다면, 몇 가지 방법이 존재합니다.

그렇지만 중앙집중형 방식이기 때문에 시스템의 확장성과 가용성에 전반적으로 문제를 일으킬 수 있습니다.

Favor composite columns over super columns


수퍼컬럼 사용시 퍼포먼스 저하가 발생할 가능성이 있다.

Cassandra 내부의 수퍼 컬럼은 column key들을 모아서 사용할 수 있고, 또는 2단계의 구조로 구성될 수 있지만 수퍼 컬럼들은 다음과 같은 구현 이슈가 존재하며 합니다.

Issues:

    • 수퍼 컬럼의 서브 컬럼은 인덱스를 사용하지 않는다. 하나의 서브 컬럼에 대한 읽기는 모든 서브 컬럼들을 비직렬화 합니다.
    • 2차 인덱스 생성은 서브컬럼에서 동작하지 않습니다.
    • 수퍼 컬럼은 두 단계 이상 암호화가 불가능합니다.

유사한 기능으로 복합컬럼 사용에 의해 압축이 가능하나 하나의 일반 컬럼은 그 안에 서브 컬럼을 암화화해 같이 저장할수 있습니다.

 이러한 기능으로 인해, 일반 컬럼의 모든 장점(정렬 , 범위 조회)은 이용 가능하고 두 단계 이상의 암호화도 가능합니다.

Note: Cassandra-3237  복합 컬럼을 사용하기 위해, 그러나, 복합 컬럼이 수퍼 컬럼보다는 보다 더 적합하다고 판단된다.

The order of sub-columns in composite columns matters


순서는 그룹화된 형태로 정의 된다.

예를 들어, <state|city>와 같은 하나의 복합 컬럼 키는 “state” ,”city” 순으로 정렬되어 저장됩니다.
다시 말하면, 하나의 state에 대한 모든 도시들은 그룹화 되어 디스크에 함께 저장됩니다.

 

Favor built-in composite types over manual construction


매뉴얼 방식이 항상  동작하는 것은 아니기 때문이다.

문자열을 결합(separators like “:” or “|”)하여 사용하는 복합 컬럼 타입을 사용하지 마시고, 대신 Cassandra 0.8.1 이상 버전에서 지원하는 내장형 복합 타입 사용을 추천합니다.

Why?

    • 매뉴얼 생성 방식은 서브 컬럼 데이타 타입이 동일하지 않다면 동작하지 않습니다.
      예를 들면 <state|zip|timeuuid>과 같은 복합 키는 잘 알려진 타입으로 정렬 기능을 지원하지 않습니다.(state as string, zip code as integer, and timeuuid as time)
    • 사용시 역정렬이 불가능 합니다. 예를 들면 위의 키타입을 사용시 state 에 대한 순차 정렬과 zip code에 대한 역정렬

Note: Cassandra의 내장된 복합 타입은 두 가지 형태가 존재합니다.

    • Static composite type : 하나의 복합컬럼의 각 부분을 위한 데이터 타입들은 각 컬럼 패밀리별로 사전에 정의됩니다. 컬럼 패밀리 내부에 존재하는 모든 컬럼 명들과 키들은 복합 구성 타입 입니다.
    • Dynamic composite type: 하나의 컬럼 패밀리 안에 서로 다른 복합 타입의 컬럼명이 혼합되있는 구조를 허용하며, 심지어 하나의 로안에도  존재하더라도 허용합니다.
      복합타입에 대해 좀더 자세한 정보를 원하면 여기로 Introduction to composite columns

Favor static composite types over dynamic, whenever possible


동적 복합 타입은 너무 동적이기 때문이다.

만약 하나의 컬럼 패밀리에 존재하는 모든 컬럼키들이 동일한 복합타입이라면, 정적인 복합 타입을 사용을 추천합니다.

동적 복합 타입은 어떤 컬럼 패밀리 안에 존재하는 멀티 커스텀 인덱스를 유지목적으로 만들었으며, 절대적으로 필요한 경우가 아니라면 동적 복합타입을 사용하는 어떤 로우 안에 서로 다른 복합 타입을 혼합하지 말 것을 권장합니다.
Cassandra-3625는  동적 복합타입에 대한 심각한 이슈를 수정한 내용이 존재합니다.

Note: CQL(Cassandra Query Language)3는 클러스트된 로를 통해 컬럼 명들을 위한 정적 복합 타입을 지원한다. 어떻게 CQL 3가 넓은 로를 다루는지 좀더 자세한 정보를 원한다면 DataStax docs 를 참고하시기 바랍니다.