오류 로그를 조회하는 MySQL 기반 운영 대시보드에서 목록과 건수 조회가 각각 약 22초씩 걸렸다. 화면은 특정 플러그인과 사용자, 시간 구간을 고른 뒤 대부분을 차지하는 [INFO] 로그를 제외해 보여 줬다. 로그 테이블에 기본 키만 있어 이 조건은 매번 전체를 훑었다.
시간만 보면 인덱스를 하나 추가하면 끝날 문제처럼 보인다. 실제 조회는 조금 더 복잡했다. 상세 화면은 플러그인·사용자·시간을 함께 걸렀고, 목록은 [INFO]로 시작하지 않는 행을 세고 최신순으로 정렬했다. 단일 열 인덱스만 늘어놓으면 각 조건은 빨라져도 실제 조회 형태를 그대로 받지 못한다.
수정은 조회 형태에 맞춰 나뉘었다. 시간 단일 인덱스와 플러그인·시간, 플러그인·사용자·시간 복합 인덱스를 추가했고 로그 요약에는 16자 접두 인덱스를 붙였다. 그 결과 상세 조회는 21.916초에서 0.039밀리초, 목록은 22.105초에서 3.630밀리초, 건수 계산은 21.920초에서 2.970밀리초로 줄었다.
까다로운 부분은 “[INFO]로 시작하지 않음”이었다. 부정 접두 조건은 인덱스 범위를 직접 쓰기 어렵다. 이 데이터베이스는 이진 정렬을 사용하므로 조건을 error_summary < '[INFO]' 또는 error_summary >= '[INFO^'라는 두 범위로 바꿨다. 기존 조건과 새 조건의 결과가 353건으로 같음을 확인한 뒤에야 속도 개선을 받아들였다.
모든 느린 조회를 인덱스 부족으로 설명하지 않은 점도 중요하다. 상태와 시간을 집계하는 다른 대시보드 조회는 약 11,081행을 반환하며 1.077초가 걸렸고 옵티마이저는 여전히 전체 스캔을 골랐다. 많은 결과를 읽고 집계하는 조회에는 인덱스를 더 붙이는 것보다 조회 형태와 반환 범위를 바꾸는 편이 먼저다.
이 수치는 한 로그 분포와 이진 정렬 조건에서 측정한 결과라 다른 데이터베이스에 그대로 적용할 수 없다. 다만 느린 조회를 고칠 때는 “어느 열에 인덱스가 없는가”보다 “실제 조건·정렬·집계가 어떤 범위를 읽는가”를 먼저 봐야 한다. 부정 조건을 범위로 바꿨다면 성능 수치와 함께 결과 건수의 동일성도 검증해야 한다.