# 01단계: 운영 DB 현황 측정 (사전준비) > 운영 서버에 인덱스를 추가하기 전 현재 상태를 정확히 파악합니다. > > **진행 상태 (2026-09-15):** 모든 항목 측정 완료. 결과 요약은 [result/premeasure_summary.txt](result/premeasure_summary.txt)에 있습니다. 모든 명령은 `result/` 디렉터리에서 실행합니다. ```bash cd doc/plan/db/260915-improve-production/result ``` --- ## 1-0. 계정 권한 확인 03단계 중복 삭제(DELETE), 02단계 slow query log 켜기(`SET GLOBAL`), 04단계 `mysql.slow_log` 조회에는 `SELECT, ALTER` 외의 권한이 필요합니다. 실제 권한을 먼저 확인하세요. **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e "SHOW GRANTS;" > premeasure_grants.txt cat premeasure_grants.txt ``` **확인할 점:** - [00-overview.md의 단계별 필요 권한](00-overview.md#단계별-필요-권한) 표와 비교합니다. - 권한이 없는 작업은 관리자 계정으로 실행할지, 작업 시간 동안만 권한을 받을지 정합니다. **결과 (2026-09-15):** `GRANT SELECT, ALTER ON chocomae.*`만 있습니다. 중복 삭제(03-0-3), `SET GLOBAL`(02-1, 05), `mysql.slow_log` 조회(04-5, 07)는 관리자 계정으로 실행해야 합니다. **임시 권한 부여 후 (2026-09-15, `premeasure_grants_after.txt`):** SUPER, 최고기록 테이블 2개 INSERT·DELETE, `mysql.slow_log` SELECT 추가. 05단계에서 회수합니다. --- ## 1-1. 테이블·인덱스 크기 **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -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 > `TABLE_ROWS`는 InnoDB 추정치라 실제 행 수와 몇 % 차이가 날 수 있습니다. --- ## 1-2. 월별 적재량 (증가 속도) **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -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개월 증가 추이 - 월 평균 증가량 - 마지막 달은 측정일까지의 값이므로 평균에서 제외 --- ## 1-3. 대표 쿼리 기준값 (EXPLAIN) ### 1-3-1. 기록이 많은 선생님·앱 찾기 **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -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 ``` **결과 (2026-09-15):** ``` MaestroID AppID cnt 181 21 1089 181 1 591 389 103 562 ... ``` → 다음 단계에서 MaestroID=181, AppID=21을 사용합니다. --- ### 1-3-2. 일간 랭킹 쿼리 EXPLAIN 위에서 나온 MaestroID, AppID를 사용하세요: **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -N -r -e " EXPLAIN FORMAT=JSON SELECT BR.PlayerID, U.Name, MAX(BR.BestRecord) AS HighScore FROM best_record BR, player U WHERE BR.MaestroID = 181 AND BR.PlayerID = U.PlayerID AND YEAR(BR.RecordDateTime) = YEAR(NOW()) AND MONTH(BR.RecordDateTime) = MONTH(NOW()) AND DAYOFMONTH(BR.RecordDateTime) = DAYOFMONTH(NOW()) AND BR.AppID = 21 GROUP BY BR.PlayerID ORDER BY MAX(BR.BestRecord) DESC;" > premeasure_explain_daily_ranking.json cat premeasure_explain_daily_ranking.json ``` > `-N`(열 이름 생략)과 `-r`(이스케이프 없이 출력)이 없으면 파일 첫 줄에 `EXPLAIN` 헤더가 붙고 줄바꿈이 `\n` 글자로 저장되어 올바른 JSON이 되지 않습니다. **확인할 점:** MariaDB JSON에서는 `type`이 아니라 `access_type` 필드를 봅니다. | 필드 | 의미 | 나쁜 값 | 운영 측정값 (2026-09-15) | |---|---|---|---| | `access_type` | 접근 방식 | `ALL` (전체 스캔) | `index_merge` | | `key` 또는 `index_merge` | 사용한 인덱스 | 없음 | `MaestroID` ∩ `AppID` | | `rows` | 검사 예상 행 수 | 전체 행 수에 가까움 | 10,100 | > 운영에는 `MaestroID`, `AppID` 단일 인덱스가 있어 전체 스캔은 아닙니다. 하지만 날짜 조건은 인덱스로 거르지 못해 10,100행을 하나씩 확인합니다. 복합 인덱스 `(MaestroID, AppID, RecordDateTime)`로 이 수를 해당 날짜의 실제 기록 수 수준으로 줄이는 것이 목표입니다. --- ## 1-4. Slow Query Log 현재 설정 저장 > 설정 변경(`SET GLOBAL`)은 SUPER 권한이 필요하고 운영에 영향을 주므로, 여기서는 **현재 값만 저장**합니다. 켜는 작업은 02단계 2-1에서, 원래 값 복원은 05단계에서 이 파일을 보고 합니다. **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e " SHOW GLOBAL VARIABLES WHERE Variable_name IN ('slow_query_log', 'long_query_time', 'log_output', 'log_queries_not_using_indexes', 'slow_query_log_file');" > premeasure_slow_log_settings.txt cat premeasure_slow_log_settings.txt ``` > 이전 버전 문서의 1-4(`SET GLOBAL ...`)를 이미 성공적으로 실행했다면 저장된 값은 원래 값이 아닙니다. MariaDB 기본값은 `slow_query_log=OFF`, `long_query_time=10`, `log_output=FILE`입니다. 서버 설정 파일의 값을 확인해 05단계 복원에 사용하세요. **결과 (2026-09-15):** `slow_query_log=ON`, `long_query_time=3`, `log_output=FILE`, `log_queries_not_using_indexes=OFF`, 로그 파일 `/var/log/mysql/mariadb-slow.log` > 이전 버전 1-4의 `SET GLOBAL`은 적용되지 않았습니다 (SUPER 권한 없음. 적용됐다면 `long_query_time=1`, `log_output=TABLE`). 따라서 위 값이 05단계에서 복원할 원래 값입니다. --- ## 1-5. 최고기록 테이블 중복 점검 ### 1-5-1. 중복 상위 10개 (완료) **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -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 chocomae.jinaju.com -u jisangs -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 ``` > 결과가 없으면 `-e` 모드는 열 이름도 출력하지 않아 **빈 파일**이 됩니다. 에러는 파일이 아니라 터미널에 표시되므로, 에러 없이 빈 파일이면 중복 0건입니다. **결과 (2026-09-15):** app_highest_record는 상위 10개 조합이 각 17~33행, typing_exam_highest_record는 0건. ### 1-5-2. 전체 중복 개수 `LIMIT 10`이라 위 결과만으로는 삭제할 행 수를 알 수 없습니다. **아래 명령어를 터미널에 복사-붙여넣기해서 실행하세요:** ```bash mariadb -h chocomae.jinaju.com -u jisangs -p chocomae -e " SELECT COUNT(*) AS dup_groups, SUM(cnt - 1) AS rows_to_delete FROM (SELECT COUNT(*) AS cnt FROM app_highest_record GROUP BY MaestroID, PlayerID, AppID HAVING cnt > 1) t;" > premeasure_app_highest_dup_count.txt cat premeasure_app_highest_dup_count.txt ``` **확인할 점:** - `dup_groups`: 중복이 있는 조합 수 - `rows_to_delete`: 조합마다 1행만 남길 때 지워지는 행 수 → 03단계 3-0에서 실제 삭제 행 수와 비교 **결과 (2026-09-15):** `dup_groups` 4,823 / `rows_to_delete` 8,795 (app_highest_record 약 23만 행의 약 3.8%) **중복이 있으면:** - 03-add-indexes.md 3-0에서 UNIQUE 키 추가 전에 **점수 기준으로** 정리합니다. --- ## 1-6. 측정 결과 기록 모든 측정값을 [result/premeasure_summary.txt](result/premeasure_summary.txt)에 정리했습니다. > 이전 버전의 `cat > premeasure_summary.txt << 'EOF'` 명령은 채워 둔 요약을 빈 양식으로 덮어쓰므로 삭제했습니다. --- ## 다음 단계 ✅ 사전 측정 완료 → **02-baseline.md로 이동** (사전 측정 수치는 모두 `result/`의 txt/json 파일에 저장되어 있습니다)