데이터베이스의 로그 구조 병합 트리(LSM tree)는 병합 과정에서 키와 값을 함께 다시 쓰기 때문에 값이 클수록 쓰기 증폭이 커질 수 있다. Alex Gaetano Padula는 TidesDB에서 큰 값을 별도 로그에 저장하는 방식과, 값 분리 및 노드 크기에 따라 쓰기·읽기 성능이 달라지는 측정 결과를 소개했다.
Alex Gaetano Padula가 작성했으며 2026년 10월 9일에 게시했다.
LSM 트리 엔진은 Level 0에서 쓰기를 버퍼링하고, 정렬된 파일을 Level 1로 내보낸 뒤 상위 레벨로 병합한다. 정렬 파일에는 보통 키와 값이 나란히 저장된다. 값이 작다면 문제가 적지만, 큰 값은 병합 때마다 다시 기록되므로 쓰기 비용이 커진다. 디스크에 기록한 바이트와 애플리케이션이 쓴 바이트의 비율을 쓰기 증폭(write amplification)이라고 한다.
WiscKey 논문(Lu 등, FAST ’16)은 트리에는 키만 저장하고, 값은 한 번 기록한 뒤 별도로 보관하는 방식을 제안했다. TidesDB에서는 value_separation_threshold 이상인 값을 엔진 전체가 공유하는 값 로그(value log)에 저장한다. 키 로그(klog)에는 그 자리에 작은 논리 ID를 넣는다. 이후 병합에서는 키와 ID만 옮기고 값은 다시 쓰지 않는다.
TidesDB는 커밋 시 값을 값 로그에 한 번 추가한다. 그 뒤 쓰기 선행 로그(WAL) 레코드, 메모리 테이블, 키 로그에는 값이 복사되지 않고 키와 ID만 전달된다고 Padula는 설명한다.
TidesDB의 SSTable(정렬 문자열 테이블)은 그 자체가 B+트리인 키 로그로 구성된다. 키 로그 노드 크기는 기본 4 KB이며 btree_klog_block_size로 설정한다. 큰 값 분리 임계값의 기본값은 1 KB로, 4 KB 값을 인라인으로 보관하면 노드 하나를 가득 채울 수 있다는 점을 고려한 설정이다.
Padula는 64 KB 노드를 사용한 인라인 저장 방식도 비교했다. 측정 프로그램은 TidesDB 10에서 4 KB 값이 붙은 키 25만 개를 무작위 순서로 적재하고, 모두 한 번씩 덮어쓴 뒤 압축이 끝날 때까지 기다린다. 그 다음 키 지정 읽기 10만 건과 전체 스캔을 측정한다.
비교 대상은 값 분리 방식, 4 KB 노드를 사용하는 인라인 방식, 64 KB 노드를 사용하는 인라인 방식이다. Padula의 측정에서 값 분리 방식은 쓰기 속도가 거의 3배 빨랐고, 압축 과정에서 데이터를 다시 쓰지 않았다. 반면 64 KB 노드 방식은 압축 과정에서 5.1 GB를 다시 썼다. 노드가 커지면 스캔은 세 방식 중 가장 빨랐지만, 조회 때마다 64 KB 노드를 디코딩해야 해 키 지정 읽기는 3배 느렸다.
값 분리에도 비용이 따른다. 전체 스캔은 행마다 추가 읽기가 발생하며, 이전 값은 해당 값을 가리키는 키가 압축 과정에서 제거될 때까지 디스크에 남는다. Padula에 따르면 TidesDB의 각 키 로그는 값이 저장된 값 로그 세그먼트를 기록한다. 참조가 없는 세그먼트는 통째로 삭제하고, 일부만 비어 있는 세그먼트는 예정된 다음 압축에서 정리한다.
따라서 큰 값을 자주 쓰고 키로 읽는 테이블에는 값 분리가 유리하며, 주로 전체 스캔하는 테이블에는 더 큰 노드와 keep_values_inline 설정이 더 적합하다는 것이 Padula의 설명이다.
Padula가 만든 도구 keybench를 사용해 TidesDB와 RocksDB를 비교한 내용, 특히 BlobDB 설정과의 비교는 이 분석 글에서 확인할 수 있다.
이 글의 교정과 편집에 도움을 준 Amar Sood(@tekacs )에게 감사를 전한다.
글 공유: X · LinkedIn · Hacker News · Reddit · Bluesky
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요