: 카산드라는 key-value 저장소로 primary key에 해당하는 칼럼들이 key, primary key를 제외한 칼럼들이 value이다. 카산드라의 테이블은 primary key들의 collection이라 할 수 있고 각 key는 일반적인 데이터베이스의 row에 해당한다. 당연히 key-value 구조이기 때문에 모든 데이터가 연속적으로 저장되어 있지 않는다. 같은 테이블 안에 있는 데이터라도 각 row에 접근할 때 카산드라는 저장소의 다른 장소를 탐색할 수 있다.

 

: CQL을 사용해 table을 생성할 때 다음처럼 키를 생성할 수 있다.

CREATE TABLE test_keyspace.test_table_ex1 ( 
    code text, 
    location text, 
    sequence text, 
    description text, 
    PRIMARY KEY (code, location, name)
);

CREATE TABLE test_keyspace.test_table_ex2 ( 
    code text, 
    location text, 
    sequence text, 
    description text, 
    PRIMARY KEY ((code, id), location, name)
);

 

: 카산드라의 primary key는 크게 partition key와 cluster key로 구분할 수 있다. partition key는 primary key의 첫 번째 부분이다. test_table_ex1에서 code, test_table_ex2에서 (code, id)가 해당 테이블의 primary key다. cluster key는 primary key에서 partition key를 제외한 나머지 key를 의미한다. test_table_ex1에서 location과 name, test_table_ex2에서 location과 name이 cluster key가 되겠다. 

 

: 카산드라는 데이터를 클러스터 내에 분배한다. 분배할 때 partition key를 이용한다. partition key를 해시 알고리즘으로 변환에 토큰을 만든다. 토큰을 기준으로 클러스터 내 특정 노드에 데이터를 위치시킨다. 따라서, 같은 partition key를 가지는 모든 row들은 같은 디스크에 저장된다. 같은 partition key를 가진 데이터들을 파티션이라고 부른다. 하나의 파티션은 cluster key에 의해 정렬된 상태로 연속적으로 저장되고 하나의 디스크에 저장되기 때문에 partition에 약 2billion 정도의 칼럼을 저장할 수 있다. 만약 한 테이블에 10개의 칼럼이 있다면 파티션당 약 200 million row를 저장할 수 있다. 보통 한 partition당 100,000 row를 넘어가면 read 성능이 감소한다. 그렇기 때문에 하나의 partition에 너무 많은 row를 저장하지 않도록 데이터를 여러 partition으로 분배하는 게 중요하다.

 

: 데이터를 여러 partition으로 분배하기 위해서 partition key를 튜플처럼 묶어서 여러 칼럼으로 구성할 수 있다. 단, CQL을 사용해 where 조건절을 사용할 때 partition key의 모든 칼럼에 대한 조건을 붙여야 하기 때문에 번거롭거나 제약사항이 생긴다. cluster key도 여러 칼럼으로 구성할 수 있다. 여러 칼럼으로 구성하면 partition내 row들이 cluster key의 첫 번째 칼럼을 기준으로 일차 정렬되고, 두 번째 칼럼... 다음 칼럼들로 순차적으로 정렬된다. 그렇기 때문에 cluster key를 이용해 where 조건문으로 select한다면 where에 사용하는 cluster key 중 가장 마지막 칼럼에만 부등호 연산을 수행할 수 있다. 나머지 모든 조건은 등호만 허용된다.

 

   

 

 

* big data 처리를 위해 NoSql이 가지는 주요 특징

1. clustering : 데이터가 클러스터 안 여러 노드에 복제된다. 따라서 fault tolerance를 보장한다. 여러 노드에서 access 가능해 성능이 향상한다.

2. flexible schema : 데이터 변화에 맞춰 유연하게 스키마 변경이 가능하다.

3. Relax consistency : eventual consistency 정책을 받아들여 빠른 쓰기가 가능하다.

4. Denormalization of data : 데이터 중복을 통해 쿼리를 최적화한다.



* 카산드라란? 왜 카산드라?

: Cassandra is a fully distributed, masterless database, offering superior scalability, and fault tolerance.

1. horizontal scalability : 카산드라는 클러스터 안 노드들이 서로를 알고 있다. 외부 app 입장에서 클러스터는 하나의 entity로 보여 데이터가 어느 노드에 있는 지 신경쓰지 않아도 된다. 노드에 요청이 오면 노드는 실제 데이터가 있는 노드에 요청을 forward한다. 클러스터에 노드 추가는 쉽다. 추가할 때 데이터는 균등하게  rebalancing된다. 그래서 카산드라 클러스터의 읽기/쓰기 처리량은 노드가 증가할 때마다 linear하게 향상된다.

2. high availability : 데이터를 쓰고 지우는 데 single point of failure가 없다. masterless해 어떤 노드든지 쓰기/읽기 operation을 받을 수 있다. 데이터는 여러 노드에 복제되 노드가 failure 되어도 정상 동작한다. 

3. write optimization : RDB는 읽기에 최적화되어 있다. 따라서 데이터를 쓸 때 읽기에 효과적인 데이터 구조로 유지시키는 과정을 거쳐 쓰기 성능이 비싸다. 반면 카산드라는 데이터를 쓸 때, 데이터 변경을 하지 않고 데이터를 파일에 추가하기 때문에 쓰기 성능에 최적화 되어 있다. 그래서 데이터를 중복해서 쓸 수 있다. 그렇다고 카산드라의 읽기 성능이 나쁜 것은 아니다. 데이터 모델링을 효과적으로 하면 읽기 성능을 충분히 개선시킬 수 있다. 

4. Structured records : RDB와 같이 table, row, columns을 가지는 structured record를 가진다. 

5. Secondary indexes : RDB는 index를 통해 빠른 select가 가능하다. 카산드라도 이와 비슷한 secondary indexes가 있다. 카산드라의 secondary indexes는 RDB index만큼의 높은 수준의 index는 아니다. 적절한 상황에서 사용해야 좋은 성능을 기대할 수 있는 단점이 있다.

6. Materialized views : secondary indexes는 인덱스로 지정한 칼럼에 중복된 데이터가 많을 시 성능이 급격히 저하되는 문제가 있다. 이를 보완해 주는게 Materialized views이다. Materialized views는 특정 쿼리문의 결과를 유지하고 있는 가상 테이블로 빠른 lookup을 가능하게 한다. 대신, view를 가진 table의 쓰기는 데이터를 update하기 때문에 약간의 지연이 발생한다.

7. Efficient result ordering : 카산드라는 지정된 cluster colums을 기준으로 정렬한 채로 데이터를 저장한다. 따라서 쉽게 정렬된 결과를 얻을 수 있다.

8. tunable consistency : 카산드라는 consistency의 정도를 조절할 수 있다. 

9. writable collections : 필드의 타입으로 collection을 사용할 수 있다. collection을 사용할 수 없다면 collection을 직렬화해서 text형식으로 저장할 것이다. 이를 업데이트할 때는 클라이언트가 데이터를 읽은 후 업데이트 연산 app단에서 진행하고 다시 직렬화 후 write 해야 한다. 이는 번거롭다. 카산드라는 카산드라 자체에서 리스트 append와 같은 collection 연산을 지원해준다.

10. Rich and flexible data model : Cassandra Query Language(CQL)은 일반 rdb sql문과 유사해 친숙하게 사용할 수 있다. 스키마는 유연해 쉽게 칼럼을 추가할 수 있고 collection type을 지원한다. 하지만 join은 지원하지 않는다.

 

+ Recent posts