본문으로 건너뛰기
  1. Posts/

왜 NoSQL과 Elasticsearch는 특정 워크로드에서 유리할까? LSM 트리와 I/O까지

NineKoo9
작성자
NineKoo9
목차

이 문서는 의문을 가지고 있던 지점을 AI 에이전트와 대화하며 정리한 메모입니다. NoSQL과 Elasticsearch가 특정 워크로드에서 유리해지는 이유를 LSM 트리, 역색인, HDD·SSD I/O 관점에서 정리합니다.

왜 NoSQL과 Elasticsearch는 특정 워크로드에서 유리할까? LSM 트리와 I/O까지
#

1. NoSQL은 왜 RDBMS보다 빠른가?
#

“NoSQL이 RDBMS보다 빠르다"는 말은 조건부로만 맞다.
제품마다 데이터 모델, 저장 엔진, 일관성 모델, 분산 구조가 다르기 때문이다.
그래서 아래 항목들은 “일부 NoSQL이 특정 워크로드에서 유리해질 수 있는 이유"로 이해하는 편이 정확하다.

1-1. 조인이 없다 (가장 큰 이유 중 하나)
#

RDBMS는 정규화된 테이블을 런타임에 조인해서 데이터를 조합한다.

SELECT u.name, o.total, p.name
FROM Users u JOIN Orders o ON ... JOIN Products p ON ...

Document DB에서는 관련 데이터를 한 도큐먼트에 임베드해서 저장하는 모델을 선택할 수 있다.

{
  "user": "건홍",
  "orders": [{ "total": 5000, "product": "책" }]
}

MongoDB 문서는 임베드된 데이터 모델이 관련 데이터를 한 번의 데이터베이스 작업으로 가져오게 해 줄 수 있고, 읽기 성능 이점이 있을 수 있다고 설명한다.
다만 이것은 MongoDB의 모든 모델이 자동으로 빠르다는 뜻이 아니라, 임베딩을 선택한 모델링 방식이 읽기 경로를 단순하게 만들 수 있다는 뜻이다.

1-2. 스키마가 없어서 쓰기가 빠르다
#

이 표현은 그대로 두면 너무 단정적이다.

MongoDB 문서는 기본적으로 유연한 스키마 모델을 사용해, 같은 컬렉션의 문서들이 기본적으로 같은 필드와 데이터 타입을 가질 필요는 없다고 설명한다. 동시에 schema validation으로 제약을 줄 수도 있다고 설명한다.

즉, 더 정확한 표현은 다음에 가깝다.

  • 일부 document DB는 기본 스키마가 더 유연하다.
  • 하지만 “스키마가 없어서 무조건 쓰기가 빠르다"라고 일반화할 수는 없다.
  • 실제 쓰기 비용은 검증 규칙, 인덱스 수, 복제, durability 설정 같은 요소에도 크게 좌우된다.

1-3. 수평 확장(Sharding)이 설계에 내재되어 있다
#

이 역시 제품별 차이를 봐야 한다.

Apache Cassandra 문서는 Cassandra가 consistent hashing 기반의 dataset partitioning, multi-master replication, incremental scale-out을 사용한다고 설명한다. 이런 시스템은 분산과 파티셔닝이 아키텍처 중심에 있기 때문에 노드 증설이 더 자연스럽다.

다만 이것을 “노드를 늘리면 처리량이 항상 선형 증가한다” 로 이해하면 과하다.
실제 성능은 파티션 키 분포, 복제 수, 네트워크, 쿼리 패턴에 따라 달라진다.

1-4. ACID를 포기한 대가
#

이 문장도 범위가 너무 넓다.

일부 분산 NoSQL 시스템은 관계형 DB와 다른 일관성/트랜잭션 모델을 택한다. 예를 들어 Cassandra는 tunable consistencylast-write-wins 기반 충돌 해소를 설명하고, cross-partition transaction을 관계형 DB처럼 일반적인 기본 모델로 두지 않는다.

하지만 모든 NoSQL이 ACID를 “포기"한다고 쓰는 것은 부정확하다.
따라서 이 항목은 다음처럼 이해하는 편이 맞다.

  • 일부 NoSQL은 강한 일관성이나 범용 트랜잭션보다 가용성, 분산성, 단순한 쓰기 경로 쪽에 더 무게를 둔다.
  • 그 선택이 특정 워크로드에서 성능 이점으로 이어질 수 있다.

1-5. 디스크 저장 방식 (Column-family DB 한정)
#

원문에서 Column DB (Cassandra, HBase)라고 묶은 부분은 조금 조심해야 한다.
Cassandra는 분석용 columnar DB라기보다 wide-column / column-family 계열로 보는 편이 더 정확하다.

구분전형적인 행 중심 저장Column-family 계열의 일부 접근
저장/접근 관점행 전체 중심파티션·컬럼 그룹 중심
특화 상황행 단위 조회/갱신모델링된 접근 패턴에 맞는 키 기반 조회

즉, 이 항목의 핵심은 “모든 NoSQL이 컬럼 저장이라 빠르다"가 아니라, 데이터 모델과 저장 구조가 접근 패턴에 더 잘 맞을 수 있다는 점이다.

1-6. LSM 트리 (쓰기 성능의 핵심)
#

→ 2절에서 상세 설명

요약 비교표
#

이유핵심 효과
임베딩 기반 모델링 가능읽기 경로 단순화 가능
LSM 계열 저장 엔진작은 쓰기를 append/flush 중심으로 처리하기 쉬움
분산 구조 내장 제품 존재파티셔닝과 증설이 더 자연스러움
일관성/트랜잭션 모델 차이일부 워크로드에서 오버헤드 절감 가능
데이터 모델 최적화접근 패턴에 더 잘 맞을 수 있음

주의: 복잡한 조인, 강한 일관성, 범용 트랜잭션이 중요한 경우에는 RDBMS가 더 적합하거나 더 빠를 수 있다.


2. LSM 트리 (Log-Structured Merge Tree)
#

2-1. 핵심 아이디어
#

작은 랜덤 갱신을 메모리에 모았다가, 정렬된 파일로 내려 쓰는 구조

B-Tree 계열 저장 엔진은 논리적으로는 기존 페이지를 찾아가 갱신하는 모델에 가깝다.
LSM 계열은 작은 쓰기를 메모리에 모아 두었다가 새 sorted file을 만들어 flush/merge 하는 쪽에 가깝다.

이때 운영체제의 page cache나 스토리지 컨트롤러가 실제 I/O를 완충할 수 있으므로,
“B-Tree = 항상 물리 랜덤 쓰기” 로 단정하면 과하다.
다만 저장 엔진의 논리적 쓰기 패턴이 다르다는 점은 분명하다.

2-2. 쓰기 흐름 단계별 설명
#

LSM 트리 쓰기 흐름
쓰기 요청
① MemTable (메모리에 정렬된 구조로 쌓음)
② SSTable (디스크에 새 sorted file로 flush)
③ Compaction (여러 SSTable을 병합·정리)

① MemTable (메모리 단계)
#

  • RocksDB 문서 기준으로 새 쓰기는 먼저 memtable에 들어간다.
  • reads도 memtable을 먼저 본다. 최신 데이터가 여기에 있기 때문이다.
  • memtable이 가득 차면 더 이상 쓰지 않는 immutable memtable이 된다.

② SSTable (디스크 단계)
#

  • 백그라운드 작업이 immutable memtable을 SST file로 flush한다.
  • Cassandra 문서도 memtable이 한계에 도달하면 디스크에 flush되어 immutable SSTable이 된다고 설명한다.
  • 핵심은 기존 파일을 제자리 수정하기보다 새 정렬 파일을 만들어 내리는 구조라는 점이다.

③ Compaction (백그라운드 정리)
#

  • 여러 SSTable이 쌓이면 compaction이 이를 병합한다.
  • RocksDB 문서는 compaction이 어떤 sorted run을 merge할지, 그리고 읽기 시 어떤 sorted run들을 봐야 하는지에 직접 영향을 준다고 설명한다.
  • 즉, compaction은 단순 청소가 아니라 LSM의 읽기/쓰기 절충을 관리하는 핵심 동작이다.

2-3. 왜 순차 쓰기가 유리한가?
#

저장 장치핵심 차이의미
HDD헤드 이동과 회전 지연이 큼순차 접근이 특히 유리
SSD헤드는 없지만 erase/write 단위와 GC 비용이 있음순차적 패턴이 write amplification을 줄이기 쉬움

HDD에서는 연속된 구간을 읽고 쓰는 편이 물리적으로 유리하다.
SSD에서는 이유가 다르다. Samsung 자료는 NAND SSD가 erase-before-write 특성을 가지며, garbage collection으로 인한 write amplification이 발생한다고 설명한다. 또한 host write pattern이 sequential할 때 SSD WAF가 1에 가깝고, random pattern은 WAF를 높일 수 있다고 설명한다.

2-4. LSM 트리를 사용하는 대표 예시
#

시스템비고
Cassandra공식 문서에서 storage engine이 LSM 기반이라고 설명
RocksDBmemtable → SST → compaction 구조를 공식 위키에서 설명

원문에 있던 MongoDB, HBase, LevelDB까지 한 줄로 같은 범주에 묶어 적는 방식은 설명이 거칠어질 수 있어서, 여기서는 이번 검증에서 직접 확인한 시스템만 적는다.

2-5. LSM 트리의 단점
#

쓰기가 빠른 대신 읽기와 백그라운드 정리 비용이 따라온다.

  • Cassandra 문서는 LSM 기반 write path가 write-oriented workload에 최적화되어 있지만, read performance와 write amplification tradeoff가 있다고 설명한다.
  • Cassandra는 읽기 보완을 위해 Bloom filter를 사용한다고 설명한다.
  • compaction 자체도 여러 SSTable을 다시 읽고 새로 써야 하므로 백그라운드 I/O를 발생시킨다.

2-6. 한 줄 요약
#

“제자리에서 계속 고치기보다, 메모리에 모았다가 새 sorted file로 내리고 나중에 병합한다"는 전략이 LSM의 핵심이다.


3. Elasticsearch는 왜 검색이 빠른가?
#

3-1. 역색인 (Inverted Index) — 핵심
#

Elasticsearch 검색 속도 — 역색인 / 샤드 / 세그먼트

일반적인 행 스캔 방식에서는 "Java"를 찾으려면 문서를 하나씩 확인해야 한다.

doc1: "Java Spring 개발자 구합니다"
doc2: "Python 데이터 엔지니어 모집"
doc3: "Java 백엔드 3년 이상"

역색인은 반대로 용어 → 문서 목록 구조를 만든다.

"Java"   → [doc1, doc3]
"Spring" → [doc1]
"Python" → [doc2]

그래서 검색 시 전체 문서를 처음부터 끝까지 훑는 대신,
해당 용어의 postings list로 바로 접근할 수 있다.
즉, 핵심은 전수 스캔을 피하게 해 주는 색인 구조에 있다.

3-2. 샤드(Shard) 병렬 검색
#

인덱스를 여러 샤드로 나누면 검색 일을 분산할 수 있다.

검색 요청
    ├──→ Shard 0
    ├──→ Shard 1
    └──→ Shard 2
         결과 병합 → 응답

다만 원문처럼 “샤드 3개면 검색 시간이 이론상 1/3” 이라고 말하면 과하다.
Elastic 문서는 각 샤드가 검색을 single CPU thread에서 수행한다고 설명하면서도, 동시에 너무 많은 샤드는 검색 성능을 떨어뜨릴 수 있다고 설명한다.

즉, 더 정확한 표현은 다음과 같다.

  • 샤드는 병렬 처리의 단위가 될 수 있다.
  • 하지만 샤드 수를 늘린다고 무조건 빨라지지는 않는다.
  • 실제 shard size와 개수는 벤치마크로 조정해야 한다.

3-3. 세그먼트(Segment) — LSM과 닮은 점이 있는 부분
#

각 샤드 내부는 Lucene 세그먼트들로 구성된다.

연산처리 방식
추가새 세그먼트로 반영
삭제즉시 물리 삭제가 아니라 이후 merge에서 정리
수정내부적으로는 삭제 + 새 문서 추가에 가깝게 처리

Elastic 문서는 Elasticsearch가 near real-time search를 제공하며, 문서가 인메모리 인덱싱 버퍼에서 새 세그먼트로 기록되고, 이 세그먼트가 먼저 filesystem cache에 올라간 뒤 검색 가능해진다고 설명한다. 이 과정을 refresh라고 부른다.

또한 Elastic 문서는 세그먼트가 immutable이며, 작은 세그먼트들이 나중에 더 큰 세그먼트로 merge된다고 설명한다.

그래서 Elasticsearch는 검색 엔진 관점에서 다음처럼 이해하면 된다.

  • 검색 가능한 세그먼트를 빠르게 연다.
  • 삭제와 정리는 merge가 백그라운드에서 담당한다.
  • 덕분에 검색 경로와 인덱싱 경로를 비교적 분리해 운영할 수 있다.

3-4. 요약
#

Elasticsearch가 빠른 이유는 역색인 + 샤드 단위 분산 + immutable 세그먼트와 refresh/merge 모델이 함께 맞물리기 때문이다.

추가로 Elastic은 다음도 공식적으로 제공한다.

  • text 필드용 analyzer
  • 기본 유사도 BM25
  • Levenshtein edit distance 기반 fuzzy query

즉, Elasticsearch는 단순한 색인 라이브러리가 아니라 검색 기능 표면 자체가 넓은 분산 검색 엔진이다.


4. MySQL 전문검색 vs Elasticsearch
#

질문: MySQL도 전문검색(Full-Text Search)에 역색인을 쓰는데, 왜 Elasticsearch보다 느리거나 불편하게 느껴질 때가 있는가?

핵심은 역색인 유무 자체가 아니라, 어떤 문제를 주목적으로 설계했느냐이다.

4-1. 샤딩 없음 — 단일 노드
#

원문처럼 “MySQL은 기본적으로 한 서버 안에서 혼자 다 처리한다"라고 단순화하면 너무 거칠다.
애플리케이션 레벨 샤딩이나 다른 분산 구성이 가능하기 때문이다.

다만 MySQL의 FULLTEXT 검색은 본질적으로 트랜잭션 DB 안의 기능이고,
Elasticsearch는 샤드 분산을 기본 개념으로 둔 검색 엔진이라는 차이는 크다.

즉, 대규모 분산 검색이라는 문제에서는 Elasticsearch 쪽이 더 직접적인 해법을 제공한다.

4-2. 역색인 품질이 다르다
#

여기서 가장 중요한 정정이 필요하다.

MySQL InnoDB full-text index도 공식 문서상 inverted index design이다.
또한 MySQL은 relevance 계산, boolean search, query expansion, CJK용 built-in ngram parser도 제공한다.

따라서 차이는 “MySQL은 역색인이 없고 Elasticsearch만 있다"가 아니다.
보다 정확한 차이는 텍스트 분석과 검색 기능 표면의 폭에 있다.

기능MySQLElasticsearch
역색인지원 (FULLTEXT)지원
관련도 계산지원지원
CJK 처리ngram parser 지원analyzer 조합으로 풍부하게 설정 가능
오타 허용제한적fuzzy query 제공
분석기 구성비교적 제한적analyzer 중심으로 매우 유연

4-3. 쓰기/읽기 경쟁 (구조 차이)
#

MySQL 쪽은 InnoDB full-text index를 유지하기 위해 auxiliary index tablesfull-text index cache를 사용하고, 최근 삽입된 토큰을 캐시에 모았다가 batch flush한다.

Elasticsearch 쪽은 refresh로 새 세그먼트를 열고, 이후 merge로 정리한다.

따라서 차이를 이렇게 이해하는 편이 낫다.

  • MySQL 전문검색은 트랜잭션 DB 내부에 통합된 검색 기능이다.
  • Elasticsearch는 검색을 중심으로 세그먼트/refresh/merge 모델을 운영한다.

즉, 둘 다 색인을 유지하지만 운영 모델이 다르다.

4-4. 메모리 활용 전략이 다르다
#

이 항목도 원문 표현을 조정할 필요가 있다.

  • Elasticsearch는 공식 문서에서 filesystem cache 위에 세그먼트를 빠르게 열어 검색 가능하게 만드는 near real-time 모델을 설명한다.
  • MySQL InnoDB는 공식 문서에서 full-text index cache를 두어 최근 삽입 토큰을 임시 저장하고 batch flush한다고 설명한다.

즉, 둘 다 캐시를 활용하지만 무엇을, 어떤 목적으로, 어떤 검색 구조에 맞춰 캐시하느냐가 다르다.

4-5. 결론
#

역색인이라는 아이디어 자체는 양쪽 모두에 있다.
차이는 트랜잭션 DB에 포함된 전문검색 기능이냐,
아니면 분산 검색을 주목적으로 만든 검색 엔진이냐에 있다.

상황더 자연스러운 선택
관계형 데이터 안에서 비교적 단순한 검색MySQL 전문검색
분산 검색, analyzer 조정, fuzzy search, 검색 전용 운영Elasticsearch

5. 랜덤 I/O vs 순차 I/O — 하드웨어까지
#

질문: 결국 OS 입장에서는 파일을 여는 것인데, 왜 속도 차이가 생기는가?
질문: B-Tree와 LSM Tree의 차이가 하드웨어 레벨에서 어떻게 적용되는가?

5-1. I/O 소프트웨어 스택 — 레이어 전체 흐름
#

I/O 소프트웨어 스택 — App에서 하드웨어까지

file.write(data)를 호출했을 때의 흐름을 단순화하면 다음과 같다.

애플리케이션 (B-Tree / LSM Tree)
OS 페이지 캐시
파일시스템 (ext4 / xfs 등)
블록 계층 / 디바이스 드라이버
HDD / SSD

Linux kernel 문서는 normal reads, writes and mmaps go through the page cache라고 설명한다.
또한 ext4 문서는 구조의 위치가 절대 디스크 오프셋이 아니라 block number 기준으로 저장된다고 설명한다.

따라서 핵심은 “파일을 연다"는 사실 자체보다,
저장 엔진이 어떤 논리적 쓰기 패턴을 만들고, 파일시스템과 장치가 그것을 어떤 블록 배치로 실현하느냐에 있다.

5-2. HDD 하드웨어 — 랜덤 vs 순차의 물리적 차이
#

HDD 랜덤 I/O vs 순차 I/O — 헤드 이동 비교

HDD 성능은 대략 다음 비용으로 설명할 수 있다.

요소설명예시
Seek time헤드가 원하는 트랙으로 이동Seagate 예시에서 평균 <12ms
Rotational latency원하는 섹터가 헤드 아래로 올 때까지 대기Seagate 예시에서 평균 5.1ms
Transfer time실제 데이터를 읽거나 쓰는 시간블록 크기·전송률에 따라 달라짐

핵심은 작은 랜덤 I/O에서는 실제 전송 시간보다 위치를 찾아가는 비용이 훨씬 크다는 점이다.

  • 랜덤 I/O: seek + 회전 대기가 여러 번 반복됨
  • 순차 I/O: 한 번 위치를 잡은 뒤 연속 전송하기 쉬움

그래서 HDD에서는 순차 패턴의 이점이 특히 크게 나타난다.

5-3. B-Tree vs LSM Tree — 블록 접근 패턴 비교
#

B-Tree vs LSM Tree 블록 접근 패턴 / SSD Write Amplification

B-Tree 쓰기 (기존 페이지 갱신 중심)
#

① 관련 페이지 탐색
② 메모리에서 갱신
③ 변경 페이지를 다시 써서 반영
  • 논리적으로는 기존 위치의 페이지를 찾아가 갱신하는 모델에 가깝다.
  • 그래서 작은 갱신이 많아질수록 저장 계층에 흩어진 쓰기 압력을 만들기 쉽다.

다만 이 문장을 **“B-Tree는 무조건 매번 물리 랜덤 쓰기”**로 이해하면 안 된다.
page cache, filesystem allocation, SSD FTL이 중간에서 완충하고 재배치할 수 있기 때문이다.

LSM Tree 쓰기 (새 파일 append/flush 중심)
#

① 메모리 MemTable에 먼저 반영
② 꽉 차면 SSTable로 flush
③ 이후 compaction으로 병합
  • 논리적으로는 새 sorted file을 만들어 내리는 구조다.
  • 그래서 작은 쓰기를 더 큰 단위의 flush/merge 작업으로 묶기 쉽다.
  • 이 패턴이 HDD의 순차 I/O나 SSD의 write amplification 관리와 더 잘 맞는 경우가 많다.

SSD에서도 순차가 유리한 이유
#

항목내용
Erase-before-writeNAND는 overwrite를 직접 하지 않고 지우기-쓰기 특성을 가진다
Garbage collection유효 페이지를 옮기며 block을 비우는 과정이 필요하다
Write AmplificationGC 때문에 host write보다 더 많은 내부 write가 생길 수 있다
순차 패턴의 이점Samsung 자료 기준으로 sequential host write는 SSD WAF를 1에 가깝게 만들 수 있다

즉, SSD에서는 HDD처럼 헤드 이동이 병목은 아니지만,
GC와 WAF 때문에 쓰기 패턴이 여전히 중요하다.

5-4. 한 줄 요약
#

B-Tree 계열은 논리적으로 기존 페이지를 갱신하는 구조에 가깝고,
LSM 계열은 새 sorted file을 만들어 내리는 구조에 가깝다.
실제 물리 I/O는 커널과 장치가 완충하지만, 저장 엔진의 쓰기 패턴 차이는 성능 특성으로 드러난다.


전체 개념 연결 지도
#

NoSQL이 특정 워크로드에서 유리해지는 이유
├── 읽기 측면
│   ├── 임베딩 기반 모델링 (일부 Document DB)
│   ├── 역색인 (Elasticsearch, MySQL FTS)
│   ├── 샤드 단위 분산 검색 (Elasticsearch)
│   └── immutable 세그먼트 + refresh/merge (Elasticsearch)
└── 쓰기 측면
    ├── LSM 트리 → memtable + SSTable + compaction
    ├── 분산 제품별 consistency/transaction 모델 차이
    └── 유연한 스키마/모델링 선택지 (일부 Document DB)

랜덤 vs 순차 I/O
├── OS 레이어: page cache 경유
├── 파일시스템: block number 기준 구조 해석
├── HDD: seek + rotational latency가 큰 비용
└── SSD: garbage collection + write amplification이 핵심 비용

B-Tree vs LSM Tree (I/O 관점)
├── B-Tree: 기존 페이지 갱신 중심
└── LSM Tree: 새 sorted file flush/merge 중심

참고 자료
#