MYSQL SQL 통계
MYSQL SQL 통계는 향후 SQL 통계(DB)로 명칭이 변경될 예정입니다.
MySQL의 performance_schema.events_statements_summary_by_digest 뷰에서 제공하는 DB 자체의 SQL 통계입니다. SQL별 실행 횟수, 수행 시간, 처리 Row 수 등의 델타값을 DB에 직접 조회하지 않고 화면에서 확인할 수 있습니다.
-
에이전트가 1시간 간격으로 델타값을 계산하여 수집합니다.
-
sum_timer_wait기준으로 에이전트 옵션statements_row_limit까지 수집합니다. (기본값 5,000건) -
DBX 에이전트 1.6.10 버전 이상이 필요합니다.
설정 완료 후 약 1시간 후 데이터 수집이 시작됩니다.
사전 설정
이 화면에 데이터를 표시하려면 DB 설정과 Agent 설정 두 가지가 모두 필요합니다.
DB 설정
-
Performance Schema 활성화 (
my.cnf)변경 후 MySQL 재시작이 필요합니다.
[mysqld]
performance_schema = on -
모니터링 계정 권한 부여
에이전트가
performance_schema를 조회할 수 있도록 DB에서 권한을 부여합니다.GRANT SELECT ON performance_schema.* TO 'whatap'@'%';
Agent 설정
whatap.conf 파일에 다음 설정을 추가합니다.
statements=true
| 설정 항목 | 타입 | 기본값 | 설명 |
|---|---|---|---|
statements | boolean | false | SQL 통계 수집 활성화 |
상세 옵션
| 설정 항목 | 타입 | 기본값 | 설명 |
|---|---|---|---|
statements_interval | int | 1 | SQL 통계 수집 간격(시간 단위) |
statements_min_row | int | 10000 | SQL 통계 데이터를 수집하는 기준입니다. 아래 수집 기준을 참고하세요. |
statements_row_limit | int | 5000 | 수집 최대 건수(sum_timer_wait 기준 상위) |
수집 기준 (statements_min_row)
performance_schema.events_statements_summary_by_digest의 아래 세 가지 지표 중 하나라도 statements_min_row를 초과(OR)할 경우 해당 SQL 데이터를 수집합니다.
| 지표 | 설명 |
|---|---|
sum_rows_affected | 영향을 받은 행 수 |
sum_rows_sent | 전송된 행 수 |
sum_rows_examined | 검사한 행 수 |
고객사의 DB 워크로드에 따라 SQL 수집량이 너무 많거나 적을 경우, statements_min_row와 statements_row_limit 값을 조정하여 수집량을 제어할 수 있습니다.
MYSQL SQL 통계
기본 옵션
상단 필터 영역에서 조회 기간, 대상 인스턴스, 필터 조건 등을 설정할 수 있습니다.
-
시간: 조회할 날짜와 시간 선택
-
인스턴스: 조회 대상 DB 인스턴스 선택
-
필터: 조건별 데이터 필터링(다중 조건 시 AND 로직 적용)
-
정렬 순서: 컬럼 헤더를 클릭해 오름차순/내림차순 정렬
-
조회 건수: 테이블 표시 건수 설정
-
결과 내 검색: 조회된 결과 내에서 쿼리 키워드 검색
-
(컬럼 선택): 표시할 컬럼을 추가/삭제, 드래그로 순서 변경 가능
-
(다운로드): CSV 형식으로 내보내기
컬럼 안내
기본 정보
| 컬럼 | 설명 |
|---|---|
digest_text | 정규화된 SQL 문(리터럴 값이 ?로 치환됨) |
digest | SQL 문의 해시값 |
schema_name | SQL이 실행된 스키마(데이터베이스) 명 |
instance | SQL이 실행된 DB 인스턴스 명 |
실행 및 시간
| 컬럼 | 설명 |
|---|---|
count_star | SQL 실행 횟수 |
timer_wait | 전체 수행 시간 합계(초) |
lock_time | 테이블 락 대기 시간 합계(초) |
Row 처리
| 컬럼 | 설명 |
|---|---|
rows_affected | INSERT, UPDATE, DELETE로 변경된 Row 수 |
rows_sent | 클라이언트에 반환된 Row 수 |
rows_examined | 서버가 검토한 Row 수(스토리지 엔진 내부 처리 제외) |
임시 테이블
| 컬럼 | 설명 |
|---|---|
created_tmp_disk_tables | 디스크에 생성된 내부 임시 테이블 수 |
created_tmp_tables | 메모리에 생성된 내부 임시 테이블 수 |
조인 (Select)
| 컬럼 | 설명 |
|---|---|
select_full_join | 조인 시 인덱스 없이 Full Table Scan한 횟수 |
select_full_range_join | 조인 시 Range 스캔을 사용한 횟수 |
select_range | 첫 번째 테이블에서 인덱스 Range 스캔을 사용한 횟수 |
select_range_check | 각 Row마다 인덱스 사용 가능 여부를 재확인한 조인 횟수 |
select_scan | 첫 번째 테이블을 Full Scan한 횟수 |
정렬 (Sort)
| 컬럼 | 설명 |
|---|---|
sort_merge_passes | Sort 버퍼 부족으로 임시 파일에 병합 정렬한 횟수 |
sort_range | Range 스캔을 이용한 정렬 횟수 |
sort_rows | 정렬된 전체 Row 수 |
sort_scan | Full Scan을 이용한 정렬 횟수 |
인덱스 사용
| 컬럼 | 설명 |
|---|---|
no_index_used | 인덱스를 사용하지 않고 테이블 스캔한 횟수 |
no_good_index_used | 적절한 인덱스 없이 실행된 횟수 |
데이터 해석 가이드
튜닝 대상 SQL 식별
-
timer_wait이 높고count_star도 높은 SQL: 자주 실행되면서 느림 → 최우선 튜닝 대상 -
rows_examined / rows_sent비율이 큰 SQL: 불필요한 Row를 많이 스캔 → 인덱스 점검 -
lock_time이 높은 SQL: 락 경합 발생 → 동시성 문제 점검
인덱스 점검이 필요한 경우
-
select_full_join> 0: 조인에 사용할 인덱스 추가 검토 -
select_range_check> 0: 조인 조건과 인덱스 구성 점검 -
no_index_used> 0: 인덱스 생성 필요 -
no_good_index_used> 0: 기존 인덱스가 적절하지 않음
메모리/디스크 효율 점검
-
created_tmp_disk_tables가 높으면tmp_table_size,max_heap_table_size증설 검토 -
sort_merge_passes가 높으면sort_buffer_size증설 검토 -
created_tmp_disk_tables / created_tmp_tables비율로 디스크 전환율 확인
실전 활용 시나리오
시나리오 1. 느린 SQL 찾기
-
timer_wait기준으로 내림차순 정렬 -
상위 SQL의
count_star를 확인 → 자주 실행되면서 느린 SQL이 최우선 튜닝 대상
시나리오 2. 비효율적 SQL 찾기
-
rows_examined가 높은데rows_sent가 낮은 SQL 확인 -
인덱스가 없거나 적절하지 않아 불필요한 Row를 많이 스캔 중
-
해당 SQL의 Plan (실행 계획)을 확인하여 인덱스 추가 여부 결정
시나리오 3. 락 경합 확인
-
lock_time이 높은 SQL 확인 -
해당 테이블에 대한 동시 접근이 많거나 트랜잭션이 오래 유지되고 있을 수 있음
추가 기능
SQL 상세 보기
SQL 컬럼을 클릭하면 상세 정보 창이 열립니다. SQL 상세 창 설명은 다음을 참고하세요.
DB 참고
events_statements_summary_by_digest
화면의 데이터는 DB의 events_statements_summary_by_digest 뷰에서 가져오기 때문에, DB 설정 변경이나 데이터 삭제가 수집 데이터에 직접 영향을 줍니다.
performance_schema_digests_size
performance_schema_digests_size 파라미터는 서로 다른 SQL 패턴(digest)을 최대 몇 개까지 저장 할지 결정합니다. -1이면 자동 크기 조정(auto sizing)이 실행됩니다.
-- 예시: 아래 두 SQL은 같은 digest로 정규화됩니다.
SELECT * FROM user WHERE id = 10;
SELECT * FROM user WHERE id = 20;
→ SELECT * FROM user WHERE id = ?
digest 개수가 limit을 초과하면 새로운 SQL 패턴은 개별 통계로 집계되지 않고, DIGEST = NULL Row에 합산됩니다. 이 경우 어떤 SQL인지 식별할 수 없어 모니터링에서 일부 SQL이 누락될 수 있습니다.
-- 현재 limit 확인
SHOW VARIABLES LIKE 'performance_schema_digests_size';
-- digest 사용량 확인
SELECT COUNT(*) FROM performance_schema.events_statements_summary_by_digest;
-- overflow 여부 확인 (NULL digest에 통계가 쌓여 있으면 limit 초과)
SELECT * FROM performance_schema.events_statements_summary_by_digest WHERE DIGEST IS NULL;
TRUNCATE 초기화
TRUNCATE 명령으로 뷰를 초기화하면 기존 데이터가 모두 삭제되고 새로운 데이터가 기록됩니다. 에이전트가 수집하는 델타값도 초기화되므로 주의하세요.