데이터베이스의 로그 구조 병합 트리(LSM tree)는 병합 과정에서 키와 값을 함께 다시 쓰기 때문에 값이 클수록 쓰기 증폭이 커질 수 있다. Alex Gaetano Padula는 TidesDB에서 큰 값을 별도 로그에 저장하는 방식과, 값 분리 및 노드 크기에 따라 쓰기·읽기 성능이 달라지는 측정 결과를 소개했다.

Asad Photo Maldives

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