# Database Analysis

> 관계형 DB의 스키마, 쿼리, 인덱스, 마이그레이션을 분석하거나 설계할 때 사용한다. "이 쿼리 왜 느리지", "인덱스 뭘 걸어야 하나", "이 테이블 설계 괜찮나", "마이그레이션 안전한가", "정규화를 풀어야 하나" 같은 요청에 트리거된다. 스키마 변경의 무중단 적용 순서, 실행계획 읽는 절차, 인덱스 선정 기준을 다룬다. 애플리케이션 코드(JPA 매핑 등) 쪽 문제 판단은 java-spring-backend와 code-review를 함께 쓴다.

- Skill: `j99way99/database-analysis` (Agent Skill)
- Install (CLI): `npx skillmds@latest add j99way99/database-analysis`
- Raw SKILL.md: https://api.skillmd.com/api/skills/j99way99/database-analysis/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: j99way99 (https://skillmd.com/u/j99way99)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/j99way99/database-analysis

---


# 데이터베이스 분석

## 절차

1. **대상과 목적을 구분한다.** 셋 중 무엇인가 — 스키마 설계 검토, 느린 쿼리 개선,
   마이그레이션 안전성 확인. 목적에 따라 봐야 할 것이 다르다.
2. **추측 전에 사실을 모은다.** 테이블 행 수, 카디널리티, 실제 실행계획, 실제 파라미터 값.
   이것 없이 인덱스를 제안하지 않는다.
3. **가장 큰 비용부터 본다.** 전체 스캔 → 조인 순서 → 정렬/임시 테이블 → 반환 행 수.
4. **하나씩 바꾸고 다시 측정한다.** 여러 변경을 동시에 적용하면 무엇이 효과였는지 알 수 없다.

## 스키마 검토

- 각 테이블의 **한 행이 무엇 하나를 뜻하는지** 한 문장으로 말할 수 있는가. 못 하면 책임이 섞인 것이다.
- 자연키를 PK로 쓸 때 그 값이 바뀔 수 있는가
- NULL 이 "값 없음"인지 "해당 없음"인지 구분되는가. 의미가 두 개면 컬럼을 나눈다.
- 상태 컬럼이 문자열 자유값인가 (제약 없는 상태값은 반드시 오염된다)
- 금액·수량에 부동소수점을 쓰고 있는가
- 시각 컬럼의 타임존 기준이 명시되어 있는가
- 삭제가 물리 삭제인가 논리 삭제인가, 그리고 조회 경로 전체가 그것을 일관되게 반영하는가
- 정규화를 푸는 결정에는 **읽기 패턴 근거**가 있어야 한다. "빠를 것 같아서"는 근거가 아니다.

## 쿼리 / 인덱스

- 실행계획을 실제로 확인한다(`EXPLAIN` / `EXPLAIN ANALYZE`). 예상 비용과 실제 행 수 차이가 크면
  통계가 낡았거나 조건 추정이 틀린 것이다.
- 인덱스 선정 기준:
  - WHERE 등치 조건 컬럼을 앞에, 범위 조건 컬럼을 뒤에 둔다
  - ORDER BY 를 인덱스로 흡수할 수 있는지 본다
  - 선택도가 낮은 컬럼(값 종류가 적은 컬럼) 단독 인덱스는 대개 무용하다
  - 커버링으로 만들면 조회가 인덱스만으로 끝나는지 검토한다
- **인덱스를 추가하면 쓰기 비용이 늘어난다.** 읽기 이득과 쓰기 부담을 같이 적는다.
- 인덱스가 안 타는 흔한 이유: 컬럼에 함수/연산 적용, 타입 불일치 암묵 변환, 선행 와일드카드 LIKE,
  OR 조건 분기
- 반환 행 수를 먼저 줄인다. 페이징 없는 전체 조회는 인덱스로 구제되지 않는다.
- 큰 오프셋 페이징은 커서 기반으로 바꾸는 것을 검토한다.

## 마이그레이션 안전성

- 잠금 시간을 확인한다. 큰 테이블에 대한 컬럼 추가/타입 변경/인덱스 생성은 서비스 중단을 만들 수 있다.
- **파괴적 변경은 한 번에 하지 않는다.** 확장 → 이중 쓰기 → 백필 → 읽기 전환 → 제거 순으로 나눈다.
- NOT NULL 컬럼 추가는 기본값과 백필 계획이 같이 있어야 한다.
- 되돌리는 방법을 먼저 적는다. 되돌릴 수 없는 단계(데이터 삭제)는 별도 배포로 분리한다.
- 배포와 마이그레이션의 **순서**를 명시한다. 구버전 애플리케이션이 새 스키마에서 동작하는가.

## 보고 형식

```
현상: <측정된 사실>
원인: <실행계획/스키마 근거>
제안: <변경 1개> — 기대 효과 / 부작용(쓰기 비용, 잠금 시간)
검증: <다시 측정할 지표>
```

대상 프로젝트의 실제 스키마·테이블명·쿼리는 **그 프로젝트 안에서** 확인한다. 여기에 적지 않는다.

