cql 컬렉션(map, set, list)에는 기능도 많다. 자바로 개발되었던 이유로 cql을 사용해 탄력적으로 개발할 수 있다.
ALTER TABLE "user_status_updates"
ADD "starred_by_users" SET<text>;
ALTER TABLE "user_status_updates"
ADD "shared_by" LIST<text>;
ALTER TABLE "users"
ADD social_identities MAP<text,bigint>;
UPDATE 예제는 다음과 같다. UPDATE문은 INSERT문과 기반이 같은 upsert 이기 때문에 insert도 되고 update도 된다.
CQL 컬렉션의 가장 강력한 기능은 컬렉션에 개별 값을 저장할 수 있다.
UPDATE images SET tags = tags + { 'cute', 'cuddly' } WHERE name = 'cat.jpg';
UPDATE images SET tags = tags - { 'lame' } WHERE name = 'cat.jpg';
UPDATE plays SET players = 5, scores = scores + [ 14, 21 ] WHERE id = '123-afde';
UPDATE plays SET players = 5, scores = [ 12 ] + scores WHERE id = '123-afde';
UPDATE users SET favs['author'] = 'Ed Poe' WHERE id = 'jsmith'
UPDATE users SET favs = favs + { 'movie' : 'Cassablanca' } WHERE id = 'jsmith'
주의 할점은 list의 삭제와 변경은 성능 이슈가 있지만, map과 set의 삭제와 변경은 list에 비해 성능 이슈가 덜하다.
또한 컬렉션 컬럼에 인덱스를 사용할 수 있다. 그러나 성능 이슈가 있을 수 있는 대용량 트래픽에서는 사용하지 않는 것이 좋다.
map 컬렉션 컬럼에 보조 인덱스를 생성하면, map의 키와 map의 값 모두 인덱스가 생성된다. 따라서 맵의 키만 인덱스 생성을 원한다면 KEYS라는 오퍼레이터를 사용한다.
CREATE INDEX ON "users" (KEYS("social_identities"));
검색은 다음과 같이 진행한다.
SELECT "username", "social_identities"
FROM users
WHERE "social_identities" CONTAINS KEY 'facebook';
CQL에서는 컬렉션 컬럼을 부분적으로 읽을 수 없다. 컬렉션에서 데이터를 검색하는 유일한 방법은 컬렉션 전체를 읽는 것이다. 따라서 성능 이슈가 있는 곳에 사용할 때는 주의 깊게 사용해야 한다.
용량 제한이 있는데 컬렉션은 64KB를 넘지 않는 데이터를 포함할 수 있다. 하나의 컬렉션에 64KB 이상의 데이터를 추가할 수 없지만 컬렉션을 읽으려 하면 64KB까지만 데이터를 읽기 때문에 결과가 잘려 데이터 손실이 발생한다.
따라서 제한 없이 커질 수 있을 예정의 데이터는 컬렉션 컬럼에 적합하지 않다. 만약 계속 데이터가 커진다면 64KB 크기를 넘지 않는 여러 개의 컬렉션으로 쪼개야 한다.
카산드라 컬렉션의 다른 한계는 WHERE...IN 절을 사용해 여러 로우를 선택할 때 컬렉션을 읽을 수 없다는 점이다. 다음 쿼리는 에러가 발생한다.
SELECT * FROM "user_status_updates"
WHERE "username" = 'alice'
AND "id" IN (
1234
);
테이블에 컬렉션 컬럼이 존재하면 WHERE...IN을 사용할 때는 컬렉션이 아닌 컬럼만 명시적으로 선택해야 한다.
튜플도 지원한다.
CREATE TABLE cycling.route (race_id int, race_name text, point_id int, lat_long tuple<text, tuple<float,float>>, PRIMARY KEY (race_id, point_id));
컬럼을 사용하는 주요 포인트가 있다.
보조 인덱스는 단일 컬럼에만 적용할 수 있다. 예를 들어 education_history 컬럼이 각각 name과 year 컬럼으로 분리되어 있다면 해당 컬럼들의 주어진 값 조합으로 레코드를 효율적으로 검색할 수있는 인덱스를 생성할 수 없다. 튜플을 사용해 두 값을 단일 컬럼에 위치시키고 해당 컬럼에 인덱스를 추가해서 여러 컬럼에 인덱스를 추가한 것과 동일한 효과를 얻을 수 있다.
(카산드라의 보조 인덱스 단점을 컬렉션으로 해결할 수 있는 특징이 있다.)
튜플의 확장 개념인 사용자 정의 타입( udt)를 지원하기도 한다. 이름을 더 추가한다.
cqlsh> CREATE TYPE cycling.basic_info (
birthday timestamp,
nationality text,
weight text,
height text
);
CREATE TABLE cycling.cyclist_stats ( id uuid PRIMARY KEY, lastname text, basics FROZEN<basic_info>);
대부분의 상황에서 사용자 정의 타입은 이름이 포함된 필드와 부분 선택의 추가 이점을 제공하기 때문에 튜플보다 더 나은 선택이 될 것이다.
구분 | 셋 | 리스트 | 맵 | 튜플 | 사용자 정의 타입 |
크기 | 유연 | 유연 | 유연 | 고정 | 고정 |
개별 변경 | 가능 | 가능 | 가능 | 불가능 | 불가능 |
부분 선택 | 불가능 | 불가능 | 불가능 | 불가능 | 가능 |
이름-값 쌍 | 불가능 | 불가능 | 가능 | 불가능 | 가능 |
여러 타입 | 불가능 | 불가능 | 키와 값 | 가능 | 가능 |
인덱스 | 개별 엘리먼트 | 개별 엘리먼트 | 개별 엘리먼트 | 전체 값 | 전체 값 |
기본 키 사용 여부 | 불가능 | 불가능 | 불가능 | 가능 | 가능 |
참고
http://www.datastax.com/documentation/cql/3.3/cql/cql_reference/delete_r.html
http://docs.datastax.com/en/cql/3.3/cql/cql_reference/cqlUpdate.html
http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_collections_c.html
http://cassandra.apache.org/doc/old/CQL-3.0.html#collections
https://docs.datastax.com/en/cql/3.1/cql/cql_reference/tupleType.html
https://docs.datastax.com/en/cql/latest/cql/cql_using/useCreateUDT.html
'cassandra' 카테고리의 다른 글
[cassandra3] Partitioner의 종류 (0) | 2017.08.22 |
---|---|
[cassandra3] (0) | 2017.08.15 |
[cassandra3] commit log - Unexpected error deserializing mutation 에러 해결 (0) | 2017.08.12 |
[cassandra] node local의 의미 (0) | 2017.08.10 |
[cassandra3] select now() (0) | 2017.08.09 |