반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 받은 트랙백

글 보관함


CQL data modeling


Data modeling concepts



데이터 모델링은 아이템들이 저장될 entity들에 대해 구별/정의 하고 그 entity 들간의 관계를 짓는 프로세스이다. 여러분의 데이터 모델링을 생성하기 위해서는 접근되는 데이터들의 타입을 알아내고 perform 될 쿼리들의 타입들을 알아내야 한다. 이 두개의 요소가 데이터의 organization과 structure 구성에 주요한 역할을 한다. 또한 데이터베이스의 테이블들을 디자인하고 생성할 때에도 이 두가지 요소는 중요하게 작용한다. 때에 따라 데이터를 indexing 하는 것은 퍼포먼스 향상에 도움을 준다. 그래서 어떤 컬럼이 secondary index가 될지에 대해 정하게 된다.

카산드라에서의 데이터 모델링은 query-driven (쿼리 기반)의 방식을 사용한다. 데이터를 organizing 하기 위해 특정 쿼리를 이용해서 하게 된다는 것이죠. 쿼리는 테이블에서 데이터를 selecting 하는 도구 입니다. 스키마는 테이블에서 어떻게 데이터가 arrange 되어야 하는가에 대한 정의이구요. 카산드라의 데이터베이스 디자인은 fast read and write라는 요구조건을 기반으로 만들어 졌습니다. 그러므로 좋은 스키마 디자인은 데이터를 읽고 retrieve 하는 과정을 더 빨리 할 수 있는 디자인입니다.

반면에 관계형 데이터베이스는 테이블과 관계 디자인에 근거해서 만들어 집니다. 그 이후에 쿼리를 만들어서 사용하는 것이지요. 관계형 데이터베이스의 데이터 모델링은 table-driven (테이블 기반) 이라고 할 수 있습니다. 그리고 테이블간의 관계는 쿼리에서 table join으로 표현 됩니다.

Cassandra의 데이터모델은 조정 가능한 consistency의 특성을 가진 분할된 row store라고 얘기할 수 있습니다. 저정 가능한 consistency라는 의미는 어떤 read 혹은 right 작업에서 client application이 요청된 데이터가 어떤 consistent를 가져야 하는지를 결정한다는 겁니다. Row들은 Table 안에 있습니다. 테이블의 primary key의 첫번째 component은 partition key 입니다. 이것은 partition 안에 존재하죠. row들은 그 key의 나머지 columns에 남아있으면서 cluster 됩니다. 다른 컬럼들은 primary key 와 별도로 인덱스 될 수 있습니다. 왜냐하면 Cassandra는 distributed database로서 파티션에 의해 노드들에서 데이터들이 그룹화 되어 있을 때 read와 write 작업에 대해 효율성을 담보할 수 있기 때문입니다. 빠른 response를 기대한 다면 그 쿼리가 되도록 적은 파티션에 작용하도록 해야 합니다. consistancy 레벨을 조정하는 것은 숨어있는 또 다른 부분 이지만 이것이 데이터 모델링 프로세스에 속하지는 않습니다.

카산드라 데이터 모델링은 쿼리에 focusing 돼 있습니다. 아래 Pro Cycling statistics demonstrate의 예제에서는 특정 쿼리에 대한 카산드라 테이블 스키마가 어떻게 modeling 하는 가를 보여 줍니다. 이 데이터 모델은 entity들과 관계들을 보여 줍니다.



이 엔티티들과 그 관계들은 테이블 디자인을 할 때 참고됩니다. 한개의 테이블에 access 할 때 쿼리는 가장 잘 디자인 된 것입니다. 그래서 쿼리에 포함되어 relationship안에 구성돼 있는 모든 엔티티들은 반드시 한개의 테이블이어야만 합니다. 어떤 테이블들은 한개의 엔티티와 그것의 attribute들만으로 구성됩니다. (아래 첫번째 예제가 이 경우입니다) 다른 경우는 1개 이상의 entity와 그 속성(attributes)들을 가지는 경우입니다. 아래의 두번째 예제에 해당되는 것이죠. 하나의 카산드라 테이블에 모든 데이터가 들어가 있는 것은 관계형 데이터베이스와 구별 되는데요. 관계형 데이터베이스 같은 경우는  두개 이상의 테이블에 데이터가 들어가 있고 foreign key로 테이블들간의 데이터의 관계를 설정하게 되죠. 카산드라는 이렇게 single table - single query 방식을 사용하기 때문에 쿼리 속도가 빠르게 되는 겁니다.

이 Pro Cycleing statistics에 대한 기본 쿼리 (Q1)는 cyclist들의 리스트 입니다. 여기에는 사이클리스트의 id, firstname 그리고 lastname 이 들어가 있습니다. 이 테이블에서 사이클 선수들을 구별해 주기 위해 UUID를 사용한 id 가 있습니다. 이 테이블에서 사이클 선수들 리스트를 뽑는 간단한 쿼리를 위해 이 id 에 partition K가 있습니다. 아래 다이어그램을 보면 Pro Cycling data model에 대한 lgical model 의 portion을 보실 수 있습니다.

Query 1 : 특정 id에 해당하는 사시클 선수 이름 찾기



연관된 쿼리 (Q2) 는 특정 race 카테고리에 대한 모든 사이클 선수들을 찾는 겁니다. 카산드라에서는 테이블에 카테고리 별로 모든 사이클 선수들의 그룹이 있는 것이 훨씬 효과적으로 작동할 수 있습니다.
그러기 위해 몇개의 공통된 컬럼들이 필요합니다. (id, lastname). 여기서는 테이블의 primary key에 카테고리가 patition key (K)로 포함돼 있습니다. 그리고 이 안에 있는 id 는 partition C로 돼 있습니다. 이럼으로서 각각의 사이클 선수에 해당하는 unique 한 record들을 관리할 수 있게 됩니다.

Query 2 : 특정 카테고리 별 사이클 선수들 찾기



이상이 두개의 아주 간단한 쿼리를 보여주는 예제입니다. 좀 더 많은 예제들은 CQL을 사용한 데이터모델링 그림을 보면 아실 수 있습니다.

테이블을 디자인하는데 가장 중요한 부분은 테이블과 테이블간의 관계가 아니라는 것을 명심하시기 바랍니다. 그것은 관계형 데이터베이스의 모델링 입니다. 카산드라에 있는 데이터는 대개 한 테이블 당 한개의 쿼리 형식으로 구성됩니다. 그리고 데이터는 여러 테이블들에 반복적으로 사용됩니다. 이러한 프로세스를 denormalization이라고 합니다.
관계형 데이터베이스에서는 데이터의 중복을 피하기 위해 normalize 데이터를 사용합니다.  entity 들간의 관계는 중요합니다. 카산드라에 저장돼 있는 데이터의 순서는 데이터를 가져올 때 간편성과 속도성에 큰 영향을 미칠 수 있기 때문입니다. 스키마 디자인은 같은 테이블의 관계된 속성들을 포함함으로서 entity들간의 관계를 capture 할 수 있게 해 줍니다. 어플리케이션에서 사용하는 client-side join은 테이블 스키마가 그 관계의 복잡성을 제대로 capture 하지 못했을 때 사용하게 됩니다.




Data modeling analysis


entity와 그 관계들에 대한 모델 개념이 만들어 졌다면 이 conceptual model로부터 테이블 스키마를 생성하기 위한 예상되는 쿼리들을 사용하실 수 있습니다. 데이터 모델의 마지막 단계는 logical design의 분석을 완료하는 것입니다. 그 과정을 통해 필요한 수정사항들을 발견하고 또 수정을 할 수 있게 되는 것이죠.
이 수정작업은 partition size limitation, cost of data consistency 그리고 performance costs 등에 대한 이해를 바탕으로 진행하실 수 있습니다. 왜냐하면 여러 다른 선택 가능한 디자인들이 있을 수 있기 때문입니다.

보다 효율적으로 운영하기 위해 파티션들은 특정 limit 내에서 제한되어야 합니다. 이 파티션 size를 측량하는 두 가지 요소는 파티션 안의 값들의 갯수와 디스크에서의 파티션 size 입니다. 한 row 당 최대 컬럼수는 20억 입니다. 디스크 공간을 sizing 하는 것은 좀 더 복잡합니다. 각 테이블의 row의 갯수, 컬럼의 갯수, primary key column 들 그리고 static 컬럼등을 고려해야 합니다. 각 어플리케이션은 각각 다른 efficiency parameter들을 가질 겁니다. 가장 좋은 방법은 value의 최대 갯수를 10만 아이템 이하로  디스크 사이즈는 100MB 이하로 유지하는 겁니다.

Data redundancy 도 반드시 고려해야 할 부분 입니다. 카산드라의 distributed design 의 결과인 이 두개의 redundancy는 테이블들과 여러 partition replicate들에 중복된 데이터 들이다.

데이터는 일반적으로 여러개의 테이블에 중복된다. 이것은 write를 하는 동안 퍼포먼스에 영향을 준다. 그리고 좀 더 많은 디스크 스페이스도 필요로 한다. 사이클 선수의 이름과 아이디를 레이스 카테고리, 종료된 레이스, 사이클 선수 통계와 같은 여러개의 데이터와 함께 저장하는 것을 생각해 보자. 여러개의 테이블에 이름과 id를 저장하면 linear duplication 이 발생한다. 두개의 값들이 각각의 테이블에 저장되는 것이다. 테이블 디자인은 좀 더 높은 order duplication의 가능성을 고려해야 할 것이다. 예를 들어 unlimited keyword 들이 광범한 수의 row에 저장되는 것 등. n keyword들이 m row들에 저장되는 경우는 좋은 테이블 디자인이 아니다. 이럴 경우 좀 더 나은 디자인을 위해 테이블 스키마를 다시 생각해 보아야 한다. 해당 쿼리는 계속 생각하고 있어야 하는 것은 물론이다.

Cassandra는 replication factor에 기반해서 파티션 데이터을 복제한다. (당연히 디스크 공간을 차지하게 될 것이다.) Replication (복제) 할 때 distributed database(데이터 베이스 분산)과 디스크 저장공간의 sizing을 감안해서 해야 하는 것은 중요하다.

어플리케이션 쪽에서의 join은 퍼포먼스에 악영향을 줄 수 있다. 일반적으로 여러분은 join을 필요로 하는 쿼리에 대해 본석해야 하고 별도의 테이블에 그 join 결과를 pre-computing 하고 저장하는 것에 대해 생각해야 한다. 카산드라에서는 목표가 퍼포먼스를 위해 1 개의 테이블에 1개의 쿼리를 사용하는 것이다. LWT (LightWeight Transactions)도 퍼포먼스에 영향을 미친다. 쿼리가 LWT를 사용하는 지 여부를 고려하는 것이 필요하고 정말 필요한것이 아닐 경우 그 requirement를 remove 하는 것도 필요하다.





반응형

Comment