diff --git a/doc/plan/db/260915-improve-stage/00-overview.md b/doc/plan/db/260915-improve-stage/00-overview.md index 4a555e5..bd1ab93 100644 --- a/doc/plan/db/260915-improve-stage/00-overview.md +++ b/doc/plan/db/260915-improve-stage/00-overview.md @@ -9,12 +9,14 @@ ## 단계별 진행 -| # | 작업 | 문서 | -|---|---|---| -| **1** | 인덱스 추가 전 성능 측정 (EXPLAIN, 실행 시간) | `01-baseline.md` | -| **2** | 인덱스 추가 SQL 실행 | `02-add-indexes.md` | -| **3** | 인덱스 추가 후 성능 측정 및 비교 | `03-verify.md` | -| **4** | 체크리스트 | `04-checklist.md` | +| # | 작업 | 문서 | 소요시간 | +|---|---|---|---| +| **01** | 사전 측정: 테이블 크기, 월별 적재량, 중복 확인 | `01-premeasure.md` | 20분 | +| **02** | 인덱스 추가 전 성능 측정 (EXPLAIN, 실행 시간) | `02-baseline.md` | 15분 | +| **03** | 인덱스 추가 SQL 실행 | `03-add-indexes.md` | 5분 | +| **04** | 인덱스 추가 후 성능 측정 및 비교 | `04-verify.md` | 15분 | +| **05** | 체크리스트 | `05-checklist.md` | 10분 | +| | **총 소요시간** | | **약 1시간 15분** | --- diff --git a/doc/plan/db/260915-improve-stage/01-premeasure.md b/doc/plan/db/260915-improve-stage/01-premeasure.md new file mode 100644 index 0000000..45905a6 --- /dev/null +++ b/doc/plan/db/260915-improve-stage/01-premeasure.md @@ -0,0 +1,208 @@ +# 01단계: 사전 측정 절차 (사전준비) + +> 개선 전 현재 상태를 정확히 파악합니다. (개선 전/후 비교의 기준점) +> +> 참고: `doc/plan/db/01-improvement-overview.md`의 **7장 사전 측정 절차**와 동일 + +--- + +## 0-1. 테이블·인덱스 크기 + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +SELECT TABLE_NAME, + TABLE_ROWS AS approx_rows, + ROUND(DATA_LENGTH / 1024 / 1024, 1) AS data_mb, + ROUND(INDEX_LENGTH / 1024 / 1024, 1) AS index_mb +FROM information_schema.TABLES +WHERE TABLE_SCHEMA = 'chocomae' +ORDER BY DATA_LENGTH DESC;" > premeasure_table_sizes.txt + +cat premeasure_table_sizes.txt +``` + +**저장할 수치:** +- `best_record` data_mb, index_mb +- `typing_exam_record` data_mb, index_mb + +--- + +## 0-2. 월별 적재량 (증가 속도) + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +SELECT DATE_FORMAT(RecordDateTime, '%Y-%m') AS ym, COUNT(*) AS cnt +FROM best_record +GROUP BY ym +ORDER BY ym;" > premeasure_monthly_load.txt + +cat premeasure_monthly_load.txt +``` + +**확인할 점:** +- 최근 3개월 증가 추이 +- 월 평균 증가량 + +--- + +## 0-3. 대표 쿼리 기준값 (EXPLAIN) + +### 3-1. 기록이 많은 선생님·앱 찾기 + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +SELECT MaestroID, AppID, COUNT(*) AS cnt +FROM best_record +WHERE RecordDateTime >= NOW() - INTERVAL 30 DAY +GROUP BY MaestroID, AppID +ORDER BY cnt DESC +LIMIT 5;" > premeasure_top_maestro_app.txt + +cat premeasure_top_maestro_app.txt +``` + +**결과 예:** +``` +| MaestroID | AppID | cnt | +|-----------|-------|-----| +| 123 | 5 | 450 | +| 456 | 2 | 320 | +... +``` + +→ 다음 단계에서 사용할 값 메모 (예: MaestroID=123, AppID=5) + +--- + +### 3-2. 일간 랭킹 쿼리 EXPLAIN + +위에서 나온 MaestroID, AppID를 사용 (예: 123, 5): + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +EXPLAIN FORMAT=JSON +SELECT BR.PlayerID, U.Name, MAX(BR.BestRecord) AS HighScore +FROM best_record BR, player U +WHERE BR.MaestroID = 123 + AND BR.PlayerID = U.PlayerID + AND YEAR(BR.RecordDateTime) = YEAR('2026-09-14') + AND MONTH(BR.RecordDateTime) = MONTH('2026-09-14') + AND DAYOFMONTH(BR.RecordDateTime) = DAYOFMONTH('2026-09-14') + AND BR.AppID = 5 +GROUP BY BR.PlayerID +ORDER BY MAX(BR.BestRecord) DESC;" > premeasure_explain_daily_ranking.json + +cat premeasure_explain_daily_ranking.json +``` + +**확인할 점:** +```json +{ + "query_block": { + "select_list": [...], + "table": { + "table_name": "best_record", + "type": "ALL", ← 나쁨 (전체 스캔) + "key": null, ← 인덱스 미사용 + "rows": 1206768 ← 모든 행 스캔 + } + } +} +``` + +--- + +## 0-4. 슬로우 쿼리 로그 활성화 (선택) + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +SET GLOBAL slow_query_log = 1; +SET GLOBAL long_query_time = 1; +SET GLOBAL log_output = 'TABLE';" +``` + +**메모:** 스테이징이므로 언제든 켜도 됨 (운영은 신중하게) + +--- + +## 0-5. 최고기록 테이블 중복 점검 + +```bash +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +-- app_highest_record 중복 확인 +SELECT MaestroID, PlayerID, AppID, COUNT(*) AS cnt +FROM app_highest_record +GROUP BY MaestroID, PlayerID, AppID +HAVING cnt > 1 +ORDER BY cnt DESC +LIMIT 10;" > premeasure_app_highest_duplicates.txt + +mariadb -h mariadb.jisangs.com -u root -p chocomae -e " +-- typing_exam_highest_record 중복 확인 +SELECT MaestroID, PlayerID, WritingID, COUNT(*) AS cnt +FROM typing_exam_highest_record +GROUP BY MaestroID, PlayerID, WritingID +HAVING cnt > 1 +ORDER BY cnt DESC +LIMIT 10;" > premeasure_exam_highest_duplicates.txt + +echo "=== app_highest_record 중복 ===" && cat premeasure_app_highest_duplicates.txt +echo "=== typing_exam_highest_record 중복 ===" && cat premeasure_exam_highest_duplicates.txt +``` + +**중복이 있으면:** +- 안1에서 UNIQUE 키 추가 전에 정리 필요 + +--- + +## 0-6. 측정 결과 기록 양식 + +아래 표를 파일로 저장: + +```bash +cat > premeasure_summary.txt << 'EOF' +=== 사전 측정 결과 (2026-09-15) === + +1. 테이블 크기 + - best_record data_mb: ____ + - best_record index_mb: ____ + - typing_exam_record data_mb: ____ + - typing_exam_record index_mb: ____ + +2. 월별 적재량 + - 최근 1개월: ____ 행 + - 최근 3개월 평균: ____ 행/월 + +3. 테스트용 선생님·앱 + - MaestroID: ____ + - AppID: ____ + - 30일 기록 수: ____ + +4. 일간 랭킹 EXPLAIN + - type: ____ (현재: ALL 예상) + - key: ____ (현재: null 예상) + - rows: ____ (현재: 1206768 근처 예상) + +5. 최고기록 테이블 중복 + - app_highest_record 중복: ____ 건 + - typing_exam_highest_record 중복: ____ 건 + +6. 준비 확인 + ☐ 테이블 크기 확인 + ☐ EXPLAIN 결과 저장 + ☐ 중복 확인 + ☐ Slow query log 켜기 (선택) + +다음: 02-baseline.md로 이동 +EOF + +cat premeasure_summary.txt +``` + +--- + +## 다음 단계 + +✅ 사전 측정 완료 → **02-baseline.md로 이동** + +(사전 측정 수치가 모두 위의 txt/json 파일에 저장되었습니다) diff --git a/doc/plan/db/260915-improve-stage/01-baseline.md b/doc/plan/db/260915-improve-stage/02-baseline.md similarity index 85% rename from doc/plan/db/260915-improve-stage/01-baseline.md rename to doc/plan/db/260915-improve-stage/02-baseline.md index aeb6584..208b122 100644 --- a/doc/plan/db/260915-improve-stage/01-baseline.md +++ b/doc/plan/db/260915-improve-stage/02-baseline.md @@ -1,10 +1,12 @@ -# 1단계: 개선 전 성능 측정 (베이스라인) +# 02단계: 개선 전 성능 측정 (베이스라인) > 인덱스 추가 전 EXPLAIN과 실행 시간을 측정해 개선 효과의 기준점을 만듭니다. +> +> ⚠️ **사전 필수**: 먼저 `01-premeasure.md`를 완료하세요 (테이블 크기, 중복 확인 등) --- -## 1-1. Slow Query Log 활성화 +## 2-1. Slow Query Log 활성화 ```sql SET GLOBAL slow_query_log = 'ON'; @@ -16,7 +18,7 @@ SHOW VARIABLES LIKE 'slow_query%'; --- -## 1-2. 핵심 쿼리 EXPLAIN 분석 +## 2-2. 핵심 쿼리 EXPLAIN 분석 ### 쿼리 1: 시간별 기록 조회 (느린 예상) @@ -33,8 +35,8 @@ LIMIT 10\G mariadb -h mariadb.jisangs.com -u root -p chocomae -e " EXPLAIN FORMAT=JSON SELECT * FROM best_record WHERE MaestroID = 1 - AND DATE(RecordDateTime) = DATE(NOW()) - AND HOUR(RecordDateTime) = HOUR(NOW()) + AND RecordDateTime >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') + AND RecordDateTime < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') + INTERVAL 1 HOUR LIMIT 10;" > baseline_query1_explain.json cat baseline_query1_explain.json @@ -79,7 +81,7 @@ cat baseline_query2_explain.json --- -## 1-3. 실행 시간 측정 +## 2-3. 실행 시간 측정 ```bash cat > baseline_test.sql << 'EOF' @@ -116,7 +118,7 @@ tail baseline_results.txt # real, user, sys 시간 확인 --- -## 1-4. 결과 기록 +## 2-4. 결과 기록 **파일로 저장된 결과:** ``` @@ -139,4 +141,4 @@ baseline_results.txt ← 실행 시간 ## 다음 단계 -✅ 베이스라인 측정 완료 → **02-add-indexes.md로 이동** +✅ 베이스라인 측정 완료 → **03-add-indexes.md로 이동** diff --git a/doc/plan/db/260915-improve-stage/02-add-indexes.md b/doc/plan/db/260915-improve-stage/03-add-indexes.md similarity index 93% rename from doc/plan/db/260915-improve-stage/02-add-indexes.md rename to doc/plan/db/260915-improve-stage/03-add-indexes.md index 1115597..564ac79 100644 --- a/doc/plan/db/260915-improve-stage/02-add-indexes.md +++ b/doc/plan/db/260915-improve-stage/03-add-indexes.md @@ -4,7 +4,7 @@ --- -## 2-1. 인덱스 추가 SQL 준비 +## 3-1. 인덱스 추가 SQL 준비 ```bash cat > add_indexes.sql << 'EOF' @@ -48,7 +48,7 @@ cat add_indexes.sql # 확인 --- -## 2-2. 인덱스 추가 실행 +## 3-2. 인덱스 추가 실행 ### 스테이징이므로 언제든 가능 @@ -76,7 +76,7 @@ watch -n 10 'mariadb -h mariadb.jisangs.com -u root -p -e "SHOW PROCESSLIST\G" | --- -## 2-3. 인덱스 생성 확인 +## 3-3. 인덱스 생성 확인 ```bash mariadb -h mariadb.jisangs.com -u root -p chocomae -e "SHOW INDEXES FROM best_record;" | grep idx_ @@ -95,4 +95,4 @@ mariadb -h mariadb.jisangs.com -u root -p chocomae -e "SHOW INDEXES FROM best_re ## 다음 단계 -✅ 인덱스 추가 완료 → **03-verify.md로 이동** +✅ 인덱스 추가 완료 → **04-verify.md로 이동** diff --git a/doc/plan/db/260915-improve-stage/03-verify.md b/doc/plan/db/260915-improve-stage/04-verify.md similarity index 94% rename from doc/plan/db/260915-improve-stage/03-verify.md rename to doc/plan/db/260915-improve-stage/04-verify.md index 8964a3c..3e7d2f4 100644 --- a/doc/plan/db/260915-improve-stage/03-verify.md +++ b/doc/plan/db/260915-improve-stage/04-verify.md @@ -4,7 +4,7 @@ --- -## 3-1. EXPLAIN 재분석 +## 4-1. EXPLAIN 재분석 ### 쿼리 1: 원래 쿼리 (함수 사용 - 아직 느림) @@ -43,7 +43,7 @@ cat after_query2_improved_explain.json --- -## 3-2. 실행 시간 재측정 +## 4-2. 실행 시간 재측정 ```bash cat > verify_test.sql << 'EOF' @@ -80,7 +80,7 @@ cat verify_results.txt --- -## 3-3. 성능 비교표 +## 4-3. 성능 비교표 ```bash cat > comparison.txt << 'EOF' @@ -112,7 +112,7 @@ cat comparison.txt --- -## 3-4. Slow Query Log 확인 +## 4-4. Slow Query Log 확인 ```bash # Synology의 slow query log 확인 @@ -133,4 +133,4 @@ SELECT ... (개선된 쿼리) ## 다음 단계 -✅ 개선 효과 검증 완료 → **04-checklist.md로 이동** +✅ 개선 효과 검증 완료 → **05-checklist.md로 이동** diff --git a/doc/plan/db/260915-improve-stage/04-checklist.md b/doc/plan/db/260915-improve-stage/05-checklist.md similarity index 91% rename from doc/plan/db/260915-improve-stage/04-checklist.md rename to doc/plan/db/260915-improve-stage/05-checklist.md index acf96bc..7fccbf4 100644 --- a/doc/plan/db/260915-improve-stage/04-checklist.md +++ b/doc/plan/db/260915-improve-stage/05-checklist.md @@ -16,7 +16,7 @@ --- -## 베이스라인 측정 (01-baseline.md) +## 베이스라인 측정 (02-baseline.md) - [ ] 핵심 쿼리 EXPLAIN 분석 저장 - baseline_query1_explain.json @@ -27,7 +27,7 @@ --- -## 인덱스 추가 (02-add-indexes.md) +## 인덱스 추가 (03-add-indexes.md) - [ ] add_indexes.sql 준비 - [ ] 인덱스 추가 SQL 실행 @@ -37,7 +37,7 @@ --- -## 개선 효과 검증 (03-verify.md) +## 개선 효과 검증 (04-verify.md) - [ ] EXPLAIN 재분석 - after_query1_explain.json (함수 사용, 여전히 느림) @@ -67,10 +67,10 @@ 스테이징 테스트 성공 후: 1. **260915-improve-production 디렉토리 생성** - - 동일한 구조 (01-baseline.md ~ 04-checklist.md) + - 동일한 구조 (02-baseline.md ~ 04-checklist.md) - 새벽 2시에 실행 -2. **02-add-indexes.md 수정** +2. **03-add-indexes.md 수정** - 스테이징 결과 참고 - 운영 DB 스크립트 작성 diff --git a/doc/plan/db/260915-improve-stage/README.md b/doc/plan/db/260915-improve-stage/README.md index 871236e..57de0a8 100644 --- a/doc/plan/db/260915-improve-stage/README.md +++ b/doc/plan/db/260915-improve-stage/README.md @@ -6,13 +6,14 @@ ## 📋 문서 구조 -| # | 파일 | 설명 | -|---|---|---| -| 00 | `00-overview.md` | 전체 계획 및 사전 확인 | -| 01 | `01-baseline.md` | **현재 상태 측정** (EXPLAIN, 실행 시간) | -| 02 | `02-add-indexes.md` | **인덱스 추가 실행** | -| 03 | `03-verify.md` | **개선 효과 검증** (EXPLAIN, 성능 비교) | -| 04 | `04-checklist.md` | **최종 체크리스트** (성공 기준) | +| # | 파일 | 설명 | 소요시간 | +|---|---|---|---| +| 00 | `00-overview.md` | 전체 계획 및 사전 확인 | - | +| 01 | `01-premeasure.md` | 🔷 **먼저 이것!** 테이블 크기, 중복 확인, EXPLAIN 기준값 | 20분 | +| 02 | `02-baseline.md` | **개선 전 성능 측정** (EXPLAIN, 실행 시간) | 15분 | +| 03 | `03-add-indexes.md` | **인덱스 추가 실행** | 5분 | +| 04 | `04-verify.md` | **개선 후 성능 측정 및 비교** (EXPLAIN, 성능 비교) | 15분 | +| 05 | `05-checklist.md` | **최종 체크리스트** (성공 기준) | 10분 | --- @@ -21,13 +22,23 @@ ### 스테이징 DB에서 테스트 (Synology) ```bash -# 1. 00-overview.md 읽기 -# 2. 01-baseline.md 실행 (15분) -# 3. 02-add-indexes.md 실행 (5분) -# 4. 03-verify.md 실행 (15분) -# 5. 04-checklist.md 검증 (10분) +# 00. 00-overview.md 읽기 -# 총 소요 시간: 약 1시간 +# 01. 🔷 01-premeasure.md 실행 (20분) +# → 테이블 크기, 중복, EXPLAIN 기준값 저장 + +# 02. 02-baseline.md 실행 (15분) +# → 개선 전 성능 측정, 파일 저장 + +# 03. 03-add-indexes.md 실행 (5분) +# → 인덱스 추가 + +# 04. 04-verify.md 실행 (15분) +# → 개선 후 성능 측정, 비교 + +# 05. 05-checklist.md 검증 (10분) + +# 총 소요 시간: 약 1시간 15분 ``` --- @@ -94,6 +105,6 @@ doc/plan/db/260915-improve-stage/ ## 다음 단계 -1. **지금:** 01-baseline.md부터 시작 +1. **지금:** 01-premeasure.md부터 시작 2. **스테이징 완료 후:** 260915-improve-production 디렉토리 생성 3. **운영 서버:** 동일한 절차 (새벽 2시)