2.4. SSTable

SSTable은 key-value pair들을 담는 Data Block, 각 Data Block들에 대한 블룸필터를 갖고 있는 Filter Block 등으로 구성된다. 이 때 LevelDB 핸드북에는 Filter Block과 관련해 다음과 같이 적혀있다.

사용자가 필터를 사용하도록 leveldb를 지정하지 않으면 leveldb는 이 블록에 내용을 저장하지 않습니다

즉 블룸필터를 사용하도록 지정하지 않으면 Filter Block에 데이터를 저장하지 않는다는 것이므로, “그렇다면 블룸필터를 사용하도록 하지 않으면 Filter Block에 데이터를 쓰지 않는 거니까 쓰기(write)를 할 때 성능이 좀 더 좋아지지 않을까?” 라는 생각이 들어서 이에 관한 실험을 하기로 했다.

실험을 진행하기 전, uftrace를 이용해 블룸필터를 적용했을 때만 leveldb::FilterBlockBuilder::Addkey함수가 호출되는 것을 보고 블룸필터를 쓰지 않으면 Filter Block에 데이터를 쓰지 않는다는 것이 사실임을 확인하고 실험을 진행했다.

Hypothesis

블룸 필터를 적용하지 않으면 필터 블록에 데이터를 저장하지 않으므로, 쓰기 작업을 할 때 성능이 좀 더 향상될 것이다.
Latency는 감소하고, Throughput은 증가할 것이다.

Design

  • Controlled Variables
    • --value_size : 2,000
    • --use_existing_db : 0
    • --compression_ratio : 1
    • --benchmarks : “fillseq”
  • Independent Variables
    • --bloom_bits : 블룸필터를 적용하지 않을 땐 지정하지 않고, 블룸필터를 적용할 땐 64로 지정
  • Dependent Variables
    • Throughput
    • Latency

Experiment Environment

  • CPU : 40*Intel® Xeon® Silver 4210R CPU @2.40GHz
  • CPUCache : 14080KB

Result

  • 블룸필터를 적용했을 때와 적용하지 않았을 때 각 10번씩 측정했다
    Latency : micros/op, Throughput : MB/s

  • 블룸필터를 적용했을 때

12345678910
Latency11.19411.31411.17811.17611.02311.37411.20411.04711.11711.206
Throughput171.8169.9172.0172.0174.4169.0171.6174.0172.9171.6

Average Latency = 11.183micros/op
Average Throughput = 172.92MB/s

  • 블룸필터를 적용하지 않았을 때
12345678910
Latency10.54311.25810.28010.67410.97610.53710.72410.35310.61910.785
Throughput182.4170.8187.0180.1175.2182.5179.3185.7181.1178.3

Average Latency = 10.674micros/op
Average Throughput = 180.24MB/s

Discussion

블룸필터를 적용했을 때와 적용하지 않았을 때의 LatencyThroughput을 비교하면 다음과 같다.

  • Latency

  • Throughput

실험 전엔 블룸필터를 쓰지 않으면 쓰기를 할 때 Latency가 좀 더 낮아지고 Throughput이 좀 더 높아질 것이라 생각했는데, 실제로 블룸필터를 적용하지 않을 때가 적용했을 때에 비해 Latency가 낮게 나오고 Throughput은 높게 나오는걸 볼 수 있었다.

그러나 실험 전에는 쓰기 작업을 할 때 블룸 필터를 적용하는 경우와 적용하지 않는 경우 간에 좀 더 큰 차이가 날 것이라 생각했는데, 실제로는 Latency의 경우 하나의 key-value pair를 넣는데 있어서 0.5micros정도밖에 차이나지 않았다. 이 차이가 그리 크게 느껴지지 않아서, 왜 큰 차이가 나지 않았던 걸까에 대해 생각해봤다.

  1. db_bench의 output
    db_bench를 실행해 출력된 결과는 엄밀히 말하면 하나의 SSTable을 만드는데 걸린 시간이 아니라, 하나의 key-value pair를 처리하는데 걸린 시간을 의미한다. 따라서 db_behcn의 출력결과는 SSTable을 만드는데 걸린 시간에 대한 지표가 아니라 전체적인 쓰기 과정에 대한 지표로 봐야 한다. 그러나 하나의 key-value pair를 넣을 때마다 하나의 SSTable이 만들어지는게 아니므로, SSTable이 써지는데 걸리는 시간차이는 전체적인 쓰기 과정에 큰 영향을 주지 않을 수도 있다. 때문에 하나의 SSTable을 처리하는데 걸린 시간차이는 눈에 띄게 났을지 몰라도 전체적인 쓰기 과정에선 그 차이가 크게 나지 않은 것일 수도 있다고 생각한다.
  2. fillseq
    이 실험을 진행할 때 fillrandom이 아니라 fillseq를 사용한 이유는 fillrandom으로 실행을 진행할 경우 블룸필터를 적용할 때와 적용하지 않을 때에 대해 동일한 순서로 key를 넣어준다는 보장이 없었기 때문이었다. fillseq로 수행할 때는 compaction이 일어나지 않는다는 특징이 있는데, 이로 인해 fillseq로 수행할 때는 flush로만 만들어지는 SSTable들에 대해서만 성능 차이가 나타나게 된다. 즉 flushcompaction이 둘 다 일어나는 환경에선 SSTable들이 만들어지는 횟수가 더 많으므로 더 많은 성능차이가 나타날 수 있지만 본 실험은 flush만 일어나는 상황에서 진행됐기 때문에 SSTable이 만들어지는 횟수 자체가 적었고, 이로 인해 성능차이가 작게 나타난 것이라 생각한다.