데이터베이스 인덱스 ⑥: 운영과 한계
인덱스 시리즈 마무리. 운영 환경의 인덱스 작업은 DDL이 DB를 멈출 수 있다는 사실에서 출발해요. CREATE INDEX CONCURRENTLY의 4단계 phase와 제약, 장기 트랜잭션이 클러스터 전반의 VACUUM/IOS에 미치는 영향, 인덱스 bloat과 REINDEX, 수십억 행을 위한 파티셔닝/샤딩, Bloom Filter, 그리고 6가지 안티패턴까지 1차 자료 기준으로 정리합니다.
검색 결과가 없습니다
제목, 태그, 카테고리로 검색
인덱스 시리즈 마무리. 운영 환경의 인덱스 작업은 DDL이 DB를 멈출 수 있다는 사실에서 출발해요. CREATE INDEX CONCURRENTLY의 4단계 phase와 제약, 장기 트랜잭션이 클러스터 전반의 VACUUM/IOS에 미치는 영향, 인덱스 bloat과 REINDEX, 수십억 행을 위한 파티셔닝/샤딩, Bloom Filter, 그리고 6가지 안티패턴까지 1차 자료 기준으로 정리합니다.
PostgreSQL의 heap-organized 모델과 MySQL InnoDB의 clustered index 모델은 근본적으로 다른 세계관이에요. 같은 SQL이라도 저장 구조에 따라 plan과 비용이 전혀 달라지고, secondary index 동작·PK 선택 전략·DBMS 이전 시 함정이 모두 달라집니다. PG/MySQL/SQL Server/Oracle 비교를 1차 자료 기준으로 정리.
복합 인덱스는 컬럼들의 정렬 순서를 그대로 B-tree에 반영한 자료구조예요. 같은 세 컬럼이라도 순서를 바꾸면 전혀 다른 인덱스가 되고, leftmost prefix rule이 활용 방식을 결정합니다. ESR Rule(Equality·Sort·Range) 가이드라인, PG18 skip scan, AND vs OR, INCLUDE와의 차이까지 1차 자료 기준으로 정리.
plan에 Index Only Scan이 잡혔다고 진짜 IOS는 아니에요. PostgreSQL의 IOS는 covering(쿼리 컬럼이 인덱스에) + visibility(VM all-visible) 두 단계 조건을 모두 만족해야 Heap Fetches가 0이 됩니다. INCLUDE 절은 covering을, VACUUM은 visibility를 충족시키는 도구. INCLUDE의 leaf-only 저장 메커니즘과 인덱스 타입별 IOS 지원, 그리고 PG12 이전 insert-only Mandrill 함정까지.
인덱스가 있다고 모든 쿼리가 같은 방식으로 그 인덱스를 쓰는 건 아니에요. PostgreSQL의 Sequential / Index / Index-Only / Bitmap Scan 4가지 전략과, 옵티마이저가 통계 기반 셀렉티비티 추정으로 그 중 하나를 고르는 메커니즘을 1차 자료 기준으로 정리합니다. correlation, work_mem, BitmapAnd, Index Cond vs Filter까지.
인덱스는 검색용 보조 자료구조이고, 그 인덱스를 쓸지 말지를 결정하는 건 옵티마이저예요. 옵티마이저의 결정을 검증하는 도구가 EXPLAIN이고, 실측까지 더하는 게 EXPLAIN ANALYZE. cost가 임의 단위라는 점, 추정 vs 실측 격차가 진단의 핵심 신호라는 점, 인덱스가 있어도 안 쓰이는 4가지 패턴까지 1차 자료 기준으로 정리합니다.
PostgreSQL UPDATE는 MVCC 구현 특성상 write amplification이 발생할 수 있어요. HOT(Heap-Only Tuple) Update가 조건부로 인덱스 갱신을 회피하고, Visibility Map이 조건부로 Index-Only Scan을 가능하게 합니다. fillfactor·autovacuum·인덱스 컬럼 설계가 그 조건을 만족시키는 실무적 지렛대예요.
같은 데이터를 디스크에 어떻게 배치할 것인가 — row store는 같이 읽는 데이터를 같이, column store는 같이 계산하는 데이터를 같이 배치합니다. PostgreSQL/MySQL이 row인 이유, ClickHouse/Parquet/Snowflake가 column인 이유, 그리고 hybrid/HTAP까지 정리합니다.
DB는 행 단위로 일하지 않고 페이지 단위로 일해요. PostgreSQL 8KB / InnoDB 16KB 페이지 안에 행이 어떻게 살고, 인덱스가 어떻게 페이지 집합을 줄이고, 왜 InnoDB의 UUID PK가 위험한지를 1차 자료 기준으로 정리합니다.
WAL · fsync · group commit · doublewrite buffer · 체크포인트까지 — 커밋된 변경이 디스크에 영속적으로 남기 위한 메커니즘 전반을 1차 자료 기준으로 정리해요. PostgreSQL synchronous_commit과 MySQL innodb_flush_log_at_trx_commit으로 trade-off 다이얼을 어떻게 돌리는지까지.
ACID의 C와 CAP의 C가 같은 단어일 뿐 완전히 다른 개념이라는 점을 정리해요. Kleppmann은 "C는 ACID에 들어갈 자격이 없다"고 말하고, CAP의 C는 사실 linearizability를 의미합니다. Eventual Consistency가 데이터 손상을 회복시키지 못하는 이유와 일관성 모델 공간(linearizability/serializability/strict serializability)까지.
격리 수준 이름만 보고 동작을 판단하면 안 되는 이유. PostgreSQL의 RR(Snapshot Isolation, ANSI phantom 차단)과 InnoDB의 RR(consistent read + locking statement hybrid)이 어떻게 다른지, write skew와 lost update가 왜 DB마다 다르게 새어나오는지를 1차 자료 기준으로 정리해요.
PostgreSQL과 InnoDB가 같은 Atomicity 보장을 어떻게 다른 비용 구조로 구현하는지 — STEAL/NO-FORCE 정책, append-only vs in-place + Undo Log, ARIES 복구 vs 가시성 규칙까지 1차 자료 기준으로 정리해요.
앞선 0~4편의 JVM/OS 메모리 이론을 Elasticsearch 운영 맥락 하나로 묶는 캡스톤 편. 왜 Heap이 26~30GB에서 끊기는지(compressed oops), hybridfs가 어떤 파일만 mmap하는지, circuit breaker가 heap 40/60/95%에 왜 걸려있는지 공식 문서로 정리했어요.
JVM 프로세스 바깥, OS 커널이 관리하는 Page Cache가 무엇이고 애플리케이션 성능에 어떤 영향을 주는지 Linux 커널 공식 문서 기반으로 정리했어요. mmap, reclaim, OOM killer, 그리고 ES가 "Heap을 RAM 50% 이하로 두라"고 하는 진짜 이유까지.
JVM이 Heap 바깥에서 쓰는 메모리 — DirectByteBuffer, MaxDirectMemorySize, mmap, Foreign Memory API — 를 Oracle 공식 문서와 OpenJDK 버그 트래커 기준으로 정리했어요. 왜 Xmx만으로는 프로세스 메모리를 통제할 수 없는지.
Serial/Parallel/G1/ZGC/Shenandoah 각각이 언제 STW로 멈추고 언제 concurrent로 돌아가는지 OpenJDK JEP와 Oracle JDK 17 공식 문서 기준으로 정리했어요. Shenandoah가 Oracle JDK 빌드에 빠져있다는 사실까지.
JVM Heap이 Young/Old Generation, Eden/Survivor로 나뉘는 이유와 NewRatio·SurvivorRatio 같은 튜닝 파라미터를 Oracle JDK 17 공식 문서 기준으로 뜯어봤어요. G1에서 이 파라미터들을 왜 건드리면 안 되는지까지.
JVM 메모리 시리즈의 출발점. Class Loader, Runtime Data Areas, Execution Engine, JIT 컴파일러까지 JVM 아키텍처 전반을 정리하고, Heap 구조·GC 알고리즘 같은 메모리 세부 주제는 ①~⑤편으로 이어가요.
FULLTEXT 인덱스가 디스크를 287GB까지 먹은 경험에서 출발해, 현업 7개 플랫폼의 콘텐츠 저장 방식, InnoDB 압축의 동작 원리, Object Storage 이동의 함정, Vertical Partitioning까지 정리해요.
@Transactional의 프록시 동작 원리, 영속성 컨텍스트의 1차 캐시와 더티 체킹, 전파 속성, 그리고 실무에서 자주 발생하는 함정까지 정리했어요.
BIO에서 NIO로의 전환 이유, NIO Connector의 Poller/Acceptor 구조, Spring MVC의 요청 처리 파이프라인까지 톰캣 내부를 파헤친다.
JDBC의 매번 커넥션 생성 문제부터 HikariCP의 동작 원리, 적정 커넥션 수 공식, 데드락 방지 전략까지 DB 커넥션 풀을 깊이 있게 정리했어요.
CGI 시절부터 서블릿, 스레드 풀까지의 역사를 따라가며 톰캣의 기본 스레드 수 200의 의미와 스레드 풀 튜닝 전략을 정리한다.
ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue 등 java.util.concurrent 패키지의 고성능 동시성 자료구조와 동작 원리를 정리한다.
CPU의 원자 명령어(CAS, TAS)부터 OS 레벨 락, 애플리케이션 락, DB 락, 분산 락까지 락 메커니즘의 전체 스펙트럼을 정리한다.
임계영역, 세마포어, 뮤텍스의 개념과 차이를 OS 레벨부터 Java 구현까지 정리하고, 실무에서 흔히 혼동하는 부분을 명확히 해봤어요.
Redis의 내부 구조부터 캐시 전략(Cache-Aside, Write-Through 등), Spring Boot 통합, 실무 주의사항까지 캐싱의 모든 것을 정리한다.
캐시와 버퍼의 개념을 CPU 캐시부터 웹 브라우저 캐시, 커널 버퍼까지 전 계층에 걸쳐 정리하고, 두 메커니즘의 근본적인 차이를 분석한다.