penti/scripts/MIGRATION_GUIDE.md

268 lines
7.0 KiB
Markdown
Raw Normal View History

2026-01-31 23:30:51 +09:00
# MySQL to PostgreSQL 데이터 마이그레이션 가이드
## 개요
make-quant-py에서 사용하던 MySQL 데이터베이스의 데이터를 새로운 PostgreSQL 데이터베이스로 마이그레이션하는 스크립트입니다.
## 마이그레이션 대상
| MySQL 테이블 | PostgreSQL 테이블 | 설명 |
|------------|------------------|------|
| `kor_ticker` | `assets` | 종목 정보 |
| `kor_price` | `price_data` | 주가 데이터 (시계열) |
| `kor_fs` | `financial_statements` | 재무제표 |
## 사전 요구사항
1. **MySQL 데이터베이스 접근 가능**
- 호스트, 사용자, 비밀번호, 데이터베이스명 확인
2. **PostgreSQL 데이터베이스 준비 완료**
- Docker Compose로 실행 중
- Alembic 마이그레이션 완료
3. **Python 의존성 설치**
```bash
pip install pymysql pandas tqdm sqlalchemy
```
## 사용 방법
### 1. 전체 데이터 마이그레이션
```bash
cd pension-quant-platform
python scripts/migrate_mysql_to_postgres.py \
--mysql-host localhost \
--mysql-user your_user \
--mysql-password your_password \
--mysql-database quant_db
```
### 2. 테스트 마이그레이션 (일부 데이터만)
```bash
python scripts/migrate_mysql_to_postgres.py \
--mysql-host localhost \
--mysql-user your_user \
--mysql-password your_password \
--mysql-database quant_db \
--price-limit 10000 \
--fs-limit 10000
```
- `--price-limit`: 주가 데이터 제한 (10,000개만)
- `--fs-limit`: 재무제표 데이터 제한 (10,000개만)
### 3. Docker 환경에서 실행
```bash
# 백엔드 컨테이너에 접속
docker-compose exec backend bash
# 마이그레이션 실행
python /app/scripts/migrate_mysql_to_postgres.py \
--mysql-host host.docker.internal \
--mysql-user root \
--mysql-password password \
--mysql-database quant_db
```
**주의**: Docker에서 호스트의 MySQL에 접근하려면 `host.docker.internal` 사용
## 마이그레이션 프로세스
### 1. 종목 데이터 (kor_ticker → assets)
- 전체 종목 조회
- UPSERT 방식으로 저장 (기존 데이터 업데이트)
- 100개 단위로 커밋
**소요 시간**: 약 1-2분
### 2. 주가 데이터 (kor_price → price_data)
- 배치 처리 (10,000개 단위)
- UPSERT 방식
- 1,000개 단위로 커밋
**소요 시간**: 데이터 양에 따라 다름
- 100만 레코드: 약 10-15분
- 1,000만 레코드: 약 1-2시간
### 3. 재무제표 데이터 (kor_fs → financial_statements)
- 배치 처리 (10,000개 단위)
- UPSERT 방식
- 1,000개 단위로 커밋
**소요 시간**: 데이터 양에 따라 다름
- 100만 레코드: 약 10-15분
- 1,000만 레코드: 약 1-2시간
## 예상 소요 시간 (전체)
| 데이터 규모 | 소요 시간 |
|-----------|---------|
| 소규모 (10만 레코드) | 5-10분 |
| 중규모 (100만 레코드) | 30분-1시간 |
| 대규모 (1,000만+ 레코드) | 2-4시간 |
## 진행 상황 모니터링
스크립트는 tqdm 프로그레스 바를 사용하여 진행 상황을 표시합니다:
```
=== 종목 데이터 마이그레이션 시작 ===
MySQL에서 2,500개 종목 데이터 읽기 완료
종목 데이터 저장: 100%|████████████| 2500/2500 [00:15<00:00, 165.43it/s]
종목 데이터 마이그레이션 완료: 2,500개
=== 주가 데이터 마이그레이션 시작 ===
전체 주가 레코드 수: 5,000,000개
배치 1: 10,000개 레코드 처리 중...
주가 데이터 저장: 100%|████████████| 10000/10000 [01:23<00:00, 120.15it/s]
...
```
## 데이터 검증
마이그레이션 후 데이터 검증:
```bash
# PostgreSQL 레코드 수 확인
curl http://localhost:8000/api/v1/data/stats
# 응답 예시:
{
"assets": {
"total": 2500,
"active": 2500
},
"price_data": {
"total_records": 5000000
},
"financial_statements": {
"total_records": 3000000
}
}
```
## 문제 해결
### 1. 연결 오류
**오류**: `pymysql.err.OperationalError: (2003, "Can't connect to MySQL server")`
**해결**:
- MySQL 서버가 실행 중인지 확인
- 호스트, 포트 정보 확인
- 방화벽 설정 확인
### 2. 메모리 부족
**오류**: `MemoryError`
**해결**:
- `--price-limit`, `--fs-limit` 옵션 사용
- 배치 크기 조정 (스크립트 내 `batch_size` 변수)
### 3. 중복 키 오류
**오류**: `IntegrityError: duplicate key value`
**해결**:
- UPSERT 로직이 자동으로 처리
- 이미 마이그레이션된 데이터는 업데이트됨
### 4. 느린 속도
**해결**:
- PostgreSQL 인덱스 임시 비활성화
- `maintenance_work_mem` 증가
- 병렬 처리 고려
## 재실행
마이그레이션은 UPSERT 방식이므로 여러 번 실행 가능합니다:
- 기존 데이터: 업데이트
- 신규 데이터: 삽입
중단된 경우 다시 실행하면 이어서 진행됩니다.
## 주의사항
1. **백업**: MySQL 데이터베이스 백업 권장
2. **디스크 공간**: PostgreSQL에 충분한 공간 확보
3. **네트워크**: 안정적인 연결 필요
4. **타임아웃**: 대용량 데이터는 타임아웃 설정 조정
## 예시
### 실제 사용 예시 (make-quant-py 데이터)
```bash
python scripts/migrate_mysql_to_postgres.py \
--mysql-host localhost \
--mysql-user root \
--mysql-password mypassword \
--mysql-database quant
# 출력:
============================================================
MySQL → PostgreSQL 데이터 마이그레이션 시작
시작 시간: 2025-01-29 15:30:00
============================================================
=== 종목 데이터 마이그레이션 시작 ===
MySQL에서 2,547개 종목 데이터 읽기 완료
종목 데이터 저장: 100%|████████| 2547/2547 [00:18<00:00]
종목 데이터 마이그레이션 완료: 2,547개
=== 주가 데이터 마이그레이션 시작 ===
전체 주가 레코드 수: 4,832,156개
배치 1: 10,000개 레코드 처리 중...
주가 데이터 저장: 100%|████████| 10000/10000 [01:25<00:00]
...
주가 데이터 마이그레이션 완료: 4,832,156개
=== 재무제표 데이터 마이그레이션 시작 ===
전체 재무제표 레코드 수: 2,145,789개
배치 1: 10,000개 레코드 처리 중...
재무제표 데이터 저장: 100%|████████| 10000/10000 [01:30<00:00]
...
재무제표 데이터 마이그레이션 완료: 2,145,789개
============================================================
마이그레이션 완료!
종료 시간: 2025-01-29 17:45:00
소요 시간: 2:15:00
============================================================
```
## 대안: CSV 내보내기/가져오기 (빠른 방법)
대용량 데이터의 경우 CSV를 통한 마이그레이션이 더 빠를 수 있습니다:
### 1. MySQL에서 CSV 내보내기
```sql
SELECT * FROM kor_price
INTO OUTFILE '/tmp/kor_price.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
```
### 2. PostgreSQL로 가져오기
```sql
COPY price_data(ticker, timestamp, open, high, low, close, volume)
FROM '/tmp/kor_price.csv'
DELIMITER ','
CSV HEADER;
```
이 방법이 Python 스크립트보다 10-100배 빠를 수 있습니다.