러스트(Rust)로 만든 컬럼형 DB, io_uring, SIMD, 그리고 비동기(Async) 회피 전략
러스트(Rust)로 개발된 임베디드 컬럼형 데이터베이스 'Frigatebird'는 푸시 기반(Push-based) 쿼리 실행 모델을 사용함
io_uring, SIMD, LZ4 압축 등 다양한 기술을 활용하여 I/O 성능을 최적화하고, 3단계 캐싱(Three-tier Caching)을 통해 데이터 접근 속도를 향상시킴
데이터베이스 설계 시 비동기/대기(Async/Await) 대신 멀티 스레딩(Multi-threading)을 선택한 배경을 설명함
SQL 지원, WAL(Write-Ahead Logging) 기반의 데이터 내구성(Data Durability), 다양한 데이터 타입(Data Types) 지원
푸시 기반(Push-based) 쿼리 실행 모델
Frigatebird는 푸시 기반(Push-based) 실행 모델을 채택하여 각 연산자가 데이터를 하위 단계로 전달한다. 이러한 방식은 병렬 처리(Parallel Processing)를 자연스럽게 가능하게 하며, 데이터는 50,000행 단위의 '모르셀(Morsel)'로 처리된다. 특히, 각 단계는 독립적으로 실행되므로, 여러 워커(Worker) 간의 병렬 처리를 통해 쿼리 성능을 극대화한다.
Late Materialization을 통한 I/O 감소
Frigatebird는 Late Materialization 기법을 사용하여 필요한 열(Column)만 로드한다. 예를 들어, 187,000행의 데이터에서 age, city, name 열을 선택하는 경우, Late Materialization을 사용하면 226,000개의 값만 로드하여 70%의 데이터 로딩 감소 효과를 얻을 수 있다. 이는 I/O 부하를 줄여 쿼리 성능을 향상시키는 핵심 요소이다.
io_uring 및 O_DIRECT를 활용한 비동기 I/O 최적화
Frigatebird는 io_uring과 O_DIRECT를 사용하여 OS 페이지 캐시(Page Cache)를 우회하는 비동기 I/O(Asynchronous I/O)를 구현했다. 이를 통해 디스크 I/O 성능을 향상시키고, 쓰기-선행 로그(Write-Ahead Logging, WAL)를 통해 데이터 내구성을 보장한다. 또한, LZ4 압축을 사용하여 데이터 저장 공간을 효율적으로 관리한다.
SIMD 및 딕셔너리 인코딩을 통한 성능 향상
Frigatebird는 SIMD(Single Instruction, Multiple Data)를 활용하여 비트맵 연산을 통해 CPU 사이클 당 64개의 행을 처리한다. 또한, 낮은 카디널리티(Cardinality)의 문자열 열에 대해 딕셔너리 인코딩(Dictionary Encoding)을 적용하여 데이터 압축 효율을 높인다. 이러한 기술들은 쿼리 처리 속도를 향상시키는 데 기여한다.
비동기/대기(Async/Await) 회피 및 멀티 스레딩(Multi-threading) 선택
저자는 Frigatebird 개발 시 비동기/대기(Async/Await) 대신 멀티 스레딩(Multi-threading)을 선택했다. 이는 io_uring의 복잡성을 관리하고, 락(Lock) 기반의 동기화(Synchronization)를 통해 데이터 일관성을 유지하기 위한 결정이었다. 멀티 스레딩은 모르셀(Morsel) 단위의 병렬 처리를 가능하게 하여, 데이터베이스의 전반적인 성능을 향상시킨다.