한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

게임 렉 백서 › L12 데이터베이스

인덱스 없는 쿼리 Missing index / full table scan

원인 ID db-no-index · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

그림과 실험이 있는 원본 카드로 열기 →

인덱스 없이 조건에 맞는 행을 찾으려면 테이블 전체를 읽어야 합니다(풀 스캔).

왜 새 기능 배포로 인덱스가 없는 조건 검색 추가 → 그러면 수백만 행을 모두 스캔해 쿼리 하나에 수백 ms~수 초 → 화면에서는 우편함·거래 기록 로딩 지연, 커넥션이 묶여 다른 요청까지 대기

증상
입력 지연, 접속 불가·무한 로딩
요인
지연, 정체
누가 겪나
특정 기능만, 서버 전체
언제
특정 행동을 할 때
담당
주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라
게임개발팀 할 일
새 쿼리는 배포 전 실행 계획 검토, 인덱스 추가, 고치는 쿼리(UPDATE·DELETE)도 인덱스를 타는지 확인.
인프라팀 할 일
느린 쿼리 로그 감시, 풀 스캔 쿼리를 찾아 게임팀에 공유, 운영 중 인덱스 추가는 잠금이 짧은 온라인 방식으로 적용.
수치 감각
인덱스가 있으면 수 ms, 없으면 데이터 크기에 비례해 느려져 큰 테이블에서는 수백~수만 배.
그래프에서는
어느 순간부터 계단처럼 올라감 · DB 쿼리 지연, 읽은 행 수
확인할 곳
MySQL은 slow query log(log_queries_not_using_indexes를 켜면 인덱스를 안 쓴 쿼리도 기록)의 Rows_examined·Rows_sent, performance_schema events_statements_summary_by_digest의 SUM_NO_INDEX_USED·SUM_ROWS_EXAMINED를 보고 EXPLAIN을 돌림. PostgreSQL은 pg_stat_user_tables의 seq_scan·seq_tup_read를 보고 EXPLAIN을 돌림
이러면 맞음
배포 뒤 새로 나타난 쿼리가 돌려준 행(Rows_sent)보다 수천 배 많은 행을 읽고(Rows_examined), EXPLAIN에 테이블 전체 스캔(MySQL type ALL, PostgreSQL Seq Scan)이 나옴. 큰 테이블의 seq_tup_read가 배포 시각부터 가파르게 늘어남
이러면 아님
인덱스를 타는데도 느리면 잠금 대기(db-hot-row, db-ddl-lock)나 실행 계획 변경(db-plan-flip). 작은 테이블의 전체 스캔은 정상일 수 있음
확인 수단
인프라 도구로 확인(게임 코드 불필요)
더 알아보기
인덱스가 없으면 쓰기도 영향을 받습니다. 인덱스 없이 고치는 쿼리(UPDATE·DELETE)는 DB에 따라 스캔한 행까지 잠가 상관없는 플레이어의 저장까지 막을 수 있습니다.

출처

  1. How MySQL Uses Indexes MySQL
    인덱스가 없으면 첫 행부터 테이블 전체를 읽고 테이블이 클수록 비용이 커짐
  2. Locks Set by Different SQL Statements in InnoDB MySQL
    맞는 인덱스가 없어 테이블 전체를 스캔하면 모든 행이 잠겨 다른 사용자의 추가까지 막힘
  3. The Slow Query Log MySQL
    long_query_time(기본 10초)을 넘긴 쿼리 기록, 인덱스를 안 쓰는 쿼리도 따로 기록 가능
  4. CREATE INDEX (PostgreSQL Documentation) PostgreSQL
    CONCURRENTLY로 만들면 쓰기를 막지 않고 인덱스 생성, 일반 생성은 끝날 때까지 쓰기를 막음
  5. Statement Summary Tables MySQL
    events_statements_summary_by_digest: 같은 모양 쿼리별 SUM_NO_INDEX_USED(인덱스 없이 실행한 횟수)·SUM_ROWS_EXAMINED
  6. EXPLAIN Output Format MySQL
    type이 ALL이면 테이블 전체 스캔, 보통 인덱스를 추가해 피함
  7. The Cumulative Statistics System (PostgreSQL Documentation) PostgreSQL
    pg_stat_user_tables의 seq_scan(순차 스캔 횟수)·seq_tup_read(순차 스캔으로 읽은 행 수)
  8. Using EXPLAIN (PostgreSQL Documentation) PostgreSQL
    Seq Scan: 테이블의 모든 행을 차례로 읽는 실행 계획

함께 보면 좋은 원인

같은 층: L12 데이터베이스

같은 증상(입력 지연)의 다른 층 원인

그림과 실험이 있는 원본 카드 보기