# 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배 빠를 수 있습니다.