ALLOW FILTERING에 대하여
Cassandra 인덱싱 페이지 에서 SAI(Storage Attached Indexes)를 통해 ALLOW FILTERING 문제를 해결하는 법을 익히고 관련 실습을 해보세요.
런던 C* 서밋에서 참석자들과 이야기를 나누면서 Cassandra가 일부 CQL 쿼리에 대해서만 ALLOW FILTERING을 요구하는 이유를 사람들이 정확히 이해하지 못하고 있다는 사실을 알게 되었습니다.
왜 ALLOW FILTERING인가?
다음과 같은 테이블을 예로 들어보겠습니다.
- 1
- 2
- 3
- 4
- 5
- 6
CREATE TABLE blogs (blogId int, time1 int, time2 int, author text, content text, PRIMARY KEY(blogId, time1, time2));
다음과 같은 쿼리를 실행한다고 가정해 봅시다.
SELECT * FROM blogs;
Cassandra는 테이블 블로그가 포함하는 모든 데이터를 반환할 것입니다. 이제 특정 time1에서의 데이터만을 원한다면 time1 열에 등호 조건을 추가해야 할 것입니다.
SELECT * FROM blogs WHERE time1 = 1418306451235;
그러면 다음과 같은 에러 메시지가 뜹니다.
<em>Bad Request: Cannot execute this query as it might involve data filtering and thus may have unpredictable performance. If you want to execute this query despite the performance unpredictability, use ALLOW FILTERING.</em>
해당 쿼리를 효율적으로 수행할 수 없을지도 모른다는 것을 Cassandra가 아는 것입니다. 이는 다음과 같은 경고의 메시지입니다. “주의하세요. 이 쿼리를 이대로 실행하는 것은 바람직하지 않습니다. 컴퓨팅 리소스가 많이 소모될 것이기 때문입니다”.
Cassandra가 이 쿼리를 실행하려면 테이블 블로그의 모든 열을 검색해야 하며 그 후 time1 열에서 요청된 값을 가지고 있지 않은 열을 필터링해야만 합니다.
예를 들어 테이블에 백만 개의 행이 존재하며 그중 95%가 time1 열에 요청된 값을 가지고 있다면 쿼리가 효율성을 유지할 수 있을 것이므로 ALLOW FILTERING을 사용해도 좋습니다.
반면 테이블에 백만 개의 행이 존재하며 그중 2개의 행만이 time1 열에 요청된 값을 가지고 있다면 쿼리의 효율성이 극도로 떨어집니다. 즉, Cassandra가 999, 998개의 행을 로드하여 얻는 소득이 전혀 없습니다. 해당 쿼리를 자주 사용한다면 time1 열에 인덱스를 추가하는 편이 좋을 것입니다.
안타깝게도 Cassandra는 위와 같은 두 사례를 구별하지 못합니다. 왜냐하면 쿼리는 테이블의 데이터 분포에 달려있기 때문입니다. 따라서 Cassandra는 사용자가 적합한 선택을 하도록 경고 메시지를 보냅니다.
보조 인덱스와 ALLOW FILTERING
인덱스 하나를 author 열에 추가하고 다음과 같은 쿼리를 수행한다고 가정해 봅시다.
SELECT * FROM blogs WHERE author = ‘Jonathan Ellis’;
Cassandra는 Jonathan이 작성한 모든 블로그를 반환할 것이며 ALLOW FILTERING을 요청하지 않을 것입니다. 이는 Cassandra가 보조 인덱스를 사용해 author 열에서 일치하는 행을 찾아낼 수 있으며 필터링을 수행할 필요가 없기 때문입니다.
하지만 다음과 같은 쿼리를 수행한다고 가정해 봅시다.
SELECT * FROM blogs WHERE author=’Jonathan Ellis’ and time2 = 1418306451235;
이때 Cassandra는 먼저 Jonathan을 author로 포함하는 행을 찾아서 로드한 다음, time2 열이 지정된 값과 일치하지 않는 행을 필터링해야 하므로 ALLOW FILTERING을 요청합니다.
이때 Time2에 인덱스를 추가하면 쿼리의 성능을 높일 수 있을 것입니다. 그러면 Cassandra는 선택성이 가장 높은 인덱스를 사용하여 로드해야 하는 행을 찾습니다. 하지만 나머지 술어를 사용하여 로드된 행을 필터링해야 하므로 ALLOW FILTERING은 여전히 필요합니다.
적합한 선택 내리기
Cassandra가 필터링이 필요하다는 이유로 쿼리를 거부한다고 해서 바로 ALLOW FILTERING을 사용해서는 곤란합니다. 이때는 데이터, 모델, 쿼리의 목적에 대해 고민해 봐야 합니다. 선택지는 언제나 다양합니다.
ALLOW FILTERING 외에도 데이터 모델 변경, 인덱스 추가, 다른 테이블 사용과 같은 선택지가 있다는 의미입니다.
따라서 구체적 사용 사례에 부합하는 적합한 선택을 내려야 합니다.