그럼 왜 실무에서 Secondary Index 를 사용하지 않고, 위와 같이 데이터 복제를 통해 사용하는 형태가 더 좋은 것일까?
예제 데이터 보기
샘플 데이터
CREATE TABLE IF NOT EXIST sec_index_test(
id BIGINT,
title TEXT NOT NULL,
view_count BIGINT,
creator TEXT,
PRIMARY KEY (id)
)
INSERT INTO sec_index_test(id, title, view_count, creator) VALUES(1, 'title1', 100, 'creator1')
INSERT INTO sec_index_test(id, title, view_count, creator) VALUES(2, 'title2', 200, 'creator2')
INSERT INTO sec_index_test(id, title, view_count, creator) VALUES(3, 'title3', 300, 'creator3')
INSERT INTO sec_index_test(id, title, view_count, creator) VALUES(4, 'title4', 400, 'creator4')
INSERT INTO sec_index_test(id, title, view_count, creator) VALUES(5, 'title5', 500, 'creator4')
//위 테이블에 대한 조회 방법
SELECT * FROM sec_index_test WHERE id = '1';
만약 creator 로 조회하고 싶다면?
CREATE INDEX IF NOT EXIST IDX_CREATOR ON sec_index_test(creator); //secondary index 생성
SELECT * FROM sec_index_test WHERE creator = 'creator4';
위와 같은 데이터를 생성한다면 어떻게 동작할까?
Secondary Index 용으로 테이블을 따로 저장한다.
creator 값은 key 가 되고, 나머지 값들은 value 로 설정되어 저장됨.
조회할 때는?
조회에 필요한 Key 를 가져온다. 그 값으로 실제 데이터를 In 쿼리와 같은 형태로 조회함.
파티션이 달라질 경우 n 번 발생 등…
저장위치 및 조회 요청…
Secondary Index 테이블에 대한 데이터는 실제 데이터와 같은 노드에 저장됨.
partition key 는 해싱한 값으로나 다른 방식으로 저장 위치를 알 수 있지만, Secondary Index 로 지정한 regular column 의 값은 저장 위치를 알 수 없다.
그렇기 때문에 코디네이터가 조회 요청을 받게 되면, 어느 노드로 가야할지 모르는 상황이므로 모든 노드에 요청을 보냄.
모든 노드에 요청을 보내야하므로 요청시간도 길어지고 응답에 대한 보장도 없어지기 때문에 해당 기능을 지양하는 것이다.
Denormalization 하는 방법
설명하기 전 예제 쿼리
//sec_index_test 에 대한 역방향에 대한 테이블
CREATE TABLE IF NOT EXIST sec_index_test_creator(
creator TEXT,
id BIGINT,
title TEXT NOT NULL,
view_count BIGINT,
PRIMARY KEY (creator, id) //PartitionKey : creator, ClusterKey : id
)
// 위 예제 데이터를 `sec_index_test_creator` 에 저장한다면 아래와 같음.
- key : creator1
- value : 1, 'title1', 100
- key : creator2
- value : 2, 'title2', 200
- key : creator3
- value : 3, 'title3', 300
- key : creator4
- value : 4, 'title4', 400
- value : 5, 'title5', 500