DBA 기초 — 데이터베이스 유지보수
데이터베이스는 사용하면서 점점 느려질 수 있습니다. 삭제된 행이 디스크 공간을 차지하고, 통계가 오래되면 옵티마이저가 비효율적인 실행 계획을 선택합니다. 정기적인 유지보수로 성능을 유지하는 방법을 알아봅니다.
VACUUM — 디스크 공간 회수
DELETE로 행을 지워도 대부분의 데이터베이스는 디스크 공간을 즉시 반환하지 않습니다. 삭제된 영역은 "빈 페이지"로 남아 파일 크기가 줄지 않습니다. VACUUM은 이 빈 공간을 회수하여 파일을 압축합니다.
ANALYZE — 통계 갱신
쿼리 옵티마이저는 테이블 통계(행 수, 값 분포, 인덱스 선택도 등)를 기반으로 실행 계획을 결정합니다. 대량 INSERT/DELETE 후 통계가 오래되면 옵티마이저가 잘못된 계획을 선택할 수 있습니다.
SQLite는 sqlite_stat1 테이블에 통계를 저장합니다. ANALYZE 실행 후 쿼리 플래너가 더 나은 인덱스를 선택하게 됩니다.
REINDEX — 인덱스 재구축
인덱스는 시간이 지나면서 단편화(fragmentation)될 수 있습니다. 대량 삭제/업데이트 후 인덱스 페이지에 빈 공간이 많아지면 성능이 저하됩니다.
백업과 복원
데이터베이스 백업은 가장 중요한 유지보수 작업입니다. 정기 백업 없이 운영하는 것은 안전벨트 없이 운전하는 것과 같습니다.
백업 규칙
- 백업은 다른 물리적 장소에 보관하세요 (같은 디스크는 의미 없음)
- 정기적으로 복원 테스트를 하세요 (복원되지 않는 백업은 백업이 아닙니다)
- 백업 파일명에 날짜를 포함하세요
모니터링 기초
문제가 발생하기 전에 미리 감지하는 것이 유지보수의 핵심입니다.
느린 쿼리 찾기
-- pg_stat_statements 확장 활성화 (postgresql.conf)
-- shared_preload_libraries = 'pg_stat_statements'
-- 가장 느린 쿼리 TOP 10
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;
-- 테이블별 순차 스캔 횟수 (인덱스 필요 여부 판단)
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
ORDER BY seq_scan DESC;
주요 모니터링 지표
| 지표 | 정상 범위 | 조치 |
|---|---|---|
| 디스크 사용량 | 80% 미만 | 공간 확보 또는 디스크 추가 |
| 느린 쿼리 수 | 일정 수준 유지 | 인덱스 추가 또는 쿼리 최적화 |
| 연결 수 | 최대치의 70% 미만 | 커넥션 풀 설정 조정 |
| 캐시 적중률 | 90% 이상 | 메모리(버퍼 풀) 증설 |
정리 표
| 작업 | SQLite | MySQL | PostgreSQL |
|---|---|---|---|
| 공간 회수 | VACUUM |
OPTIMIZE TABLE t |
VACUUM FULL t |
| 통계 갱신 | ANALYZE |
ANALYZE TABLE t |
ANALYZE t |
| 인덱스 재구축 | REINDEX |
ALTER TABLE t FORCE |
REINDEX TABLE t |
| 백업 | .backup / 파일 복사 |
mysqldump |
pg_dump |
| 복원 | 파일 복사 | mysql < dump.sql |
pg_restore |
| 느린 쿼리 | EXPLAIN QUERY PLAN |
slow query log | pg_stat_statements |
| 자동 유지보수 | 없음 | 이벤트 스케줄러 | autovacuum |
유지보수 주기 가이드
- 매일: 백업, 모니터링 지표 확인
- 매주: 느린 쿼리 로그 검토
- 매월:
ANALYZE(통계 갱신), 디스크 사용량 점검 - 분기별:
REINDEX/VACUUM FULL(필요 시)