fulltext와 table 명령어 관련 문의

안녕하세요

일반적으로 대용량의 데이터를 검색 할 때 (특정 필드의 검색할 문자열)에는 fulltext 가 빠른 것으로 알고 있었는데요.
실제 환경에서 데이터 조회 시에는 같은 조건에서 table 명령어가 더 빠른 실행 결과를 보여주더라고요.

그리하여 각 각의 명령어가 어떠한 환경에서 사용 했을 때 이점이 있을지 궁금합니다.

감사합니다.

로그프레소의 성능 특성을 이해하려면 테이블 및 인덱스 기본 구조를 이해해야 합니다.

테이블과 인덱스의 구조

로그프레소 플랫폼은 테이블과 인덱스 개념이 구분되어 있습니다. 테이블은 원본 데이터를 열 지향 레이아웃으로 변환하여 블록 단위로 적재합니다. 로그프레소는 통상 2000개의 레코드를 하나의 블록으로 분할합니다. 각 열은 압축 및 암호화된 상태로 보관됩니다.

인덱스는 블룸필터 인덱스(bloomfilter index)와 역 인덱스(inverted index) 2가지 유형으로 구분됩니다. 블룸필터 인덱스는 원본에 비하여 용량이 1/1000 수준으로 아주 작은 대신, 어떤 키워드의 존재 유무만을 확인할 수 있습니다.

역 인덱스는 책의 색인과 같은 원리로 동작합니다. 각 단어를 먼저 찾아보고 해당 단어 오른쪽에 기록된 쪽 번호를 보고 찾아가는 것처럼, 역 인덱스는 키워드를 트리 형태로 관리하며 물리적인 레코드 번호의 나열(Posting List)을 관리합니다.

성능 특성의 이해

table 쿼리 명령어를 사용하여 테이블 데이터를 순차적으로 읽는 것을 테이블 스캔이라고 합니다. 반면 fulltext 쿼리 명령어를 사용하여 인덱스를 검색하는 것을 풀텍스트 검색이라고 합니다.

fulltext 검색을 하게 되면, 아래와 같은 일이 수행됩니다:

  1. 블룸필터 인덱스를 먼저 읽어들여 키워드 존재 여부를 확인합니다. 키워드가 존재하지 않는다면 역인덱스나 테이블은 아예 조회할 필요가 없습니다. 즉 블룸필터 인덱스는 최소한의 디스크 I/O로 불필요한 일을 아예 수행하지 않기 위한 자료구조입니다.
  2. 키워드가 존재한다면 역 인덱스에서 키워드를 검색합니다. 키워드를 찾으면 물리적인 레코드 번호의 나열(Posting List)을 얻어올 수 있습니다.
  3. 물리적 레코드 번호 값에 따라 테이블 블록을 찾아서 복호화 및 압축 해제 후 데이터를 읽어들입니다.

위의 모든 과정은 디스크에서 랜덤 액세스로 수행됩니다.

이제, 키워드가 방화벽 로그의 PERMIT 처럼 너무 흔한 값이라서 풀텍스트로 검색 시 거의 대부분의 테이블 블록을 읽어들여야 하는 경우를 생각해봅시다. 어차피 모든 테이블 블록을 읽어야 하니 이 경우에는 차라리 테이블 스캔만을 수행하는게 블룸필터 인덱스나 역 인덱스에 대한 랜덤 디스크 I/O를 발생시키지 않는 경우였을 것입니다. 특히 하드디스크의 경우, 순차적인 읽기는 빠르지만 랜덤 읽기는 수십 배 이상 느리기 때문에, 풀텍스트 검색의 결과가 대부분의 테이블 블록 읽기로 귀결된다면 차라리 테이블 스캔하는 것이 유리합니다.

그러면 어느 정도 흔해야 모든 테이블 블록 읽기에 해당되는가 생각해봐야 하는데, 위에서 언급한 것처럼 테이블 블록은 약 2000개의 레코드 단위로 구성됩니다. 즉, 검색 시 레코드 2000개 중에 1개가 일치하는 빈도라면 (그리고 아주 균일하게 그 값이 섞여있다면), 1개만 포함되어 있어도 해당 블록을 읽어들여 복호화 및 압축 해제를 수행해야 하므로, 풀텍스트 검색은 불필요한 랜덤 I/O를 발생시키는 것이 되고, 원래 의도와 달리 테이블 스캔에 비해 검색 성능이 떨어집니다.

로드맵

이상적으로는 관계형 데이터베이스와 같이 Cost Optimizer가 추가되어야 합니다. fulltext 검색 키워드에 대해 미리 계산된 키워드 분포 통계 값을 확인하여 쿼리 실행 계획 수립 과정에서 테이블 스캔으로 전환하거나, 실행 도중에 대부분의 테이블 블록을 hit 하는 것으로 확인되면 테이블 스캔으로 전환하는 것입니다.

그러나 현재의 로그프레소 플랫폼은 이러한 Optimizer가 내장된 상태가 아니므로, 추후 해당 기능이 구현되기 전까지는 사용자의 경험으로 직접 쿼리를 최적화 해야 합니다.

2개의 좋아요

안녕하십니까

위 내용을 보고 질문이 생겨 문의드립니다.

fulltext와 table 명령어 사용 후 stats로 그룹핑을 시도할 경우, table 쿼리는 원활하게 그룹핑이 가능한 반면, fulltext는 그룹핑 속도가 현저히 느립니다.

이러한 현상이 검색 로직과 관련이 있을까요?

네 fulltext 결과를 단순 조회할 때는 사용자가 현재 조회 중인 페이지만 최대한 지연 읽기(Lazy load)하기 때문에 빠르지만, 그 결과를 통계 처리하려면 전체 데이터를 가져와야 하기 때문에 테이블 결과에 대해서 stats 하는 것과 달리 fulltext 결과에 대해 stats 등 후처리하는 것은 성능적인 차이가 발생합니다.