본문 바로가기

프로젝트/집안일 관리 시스템

[성능 개선] 인덱스를 사용해보자

버전

mysql 8.0.35

ngrinder 3.5.8

 

 

인덱스

인덱스는 조회를 빠르게 해주는 자료구조이다.

인덱스를 사용해서 쿼리속도를 개선하기 위해서

API 마다 발생하는 쿼리를 기록하고 

EXPLAIN을 사용해서 쿼리의 실행계획을 통해 개선할 부분이 없는지 고민했다.

 

 

유저

인덱스 사용하기

기존에는 이메일 중복여부를 확인하기 위해 다음과 같은 쿼리를 사용했다.

email은 중복이 되지 않아야 하므로 unique 제약조건을 달았고 기본적으로 논클러스터드 인덱스가 걸린다.

where 절에서 email을 사용하기 때문에 Index Unique Scan을 사용해서 탐색한다.

select
    user0_.users_id as users_id1_6_,
    user0_.created_time as created_2_6_,
    user0_.modified_time as modified3_6_,
    user0_.best_mate_count as best_mat4_6_,
    user0_.delete_status as delete_s5_6_,
    user0_.email as email6_6_,
    user0_.name as name7_6_,
    user0_.nickname as nickname8_6_,
    user0_.password as password9_6_,
    user0_.phone_number as phone_n10_6_,
    user0_.profile_img as profile11_6_,
    user0_.provider as provide12_6_ 
from
    users user0_ 
where
    user0_.email=?
table type key extra
user0_ const user_idx null

 

index unique scan을 한 뒤에는 select 절에 있는 정보를 찾기 위해

기본적으로 클러스터드 인덱스로 사용하는 id로 데이터 블록을 탐색한다.

하지만 해당 기능에서는 이메일 중복 여부만 알면 되지 그 외 유저 정보는 필요가 없다. 

이때 select 절에서 id만 가져오게 되면 데이터 블록을 탐색하는 과정이 필요 없게 된다.

이를 커버링 인덱스라고 한다.

select
    user0_.users_id as users_id1_6_
from
    users user0_ 
where
    user0_.email=?
table type key extra
user0_ const user_idx Using index

 

 

 

할 일

인덱스 사용하기

할 일을 조회하는 경우 최신순으로 조회하는데

인덱스가 설정되어 있지 않은 경우 소트 버퍼에 레코드를 복사해서 정렬한다.

select
    todaytodo0_.todo_id as todo_id2_4_,
    todaytodo0_.created_time as created_3_4_,
    todaytodo0_.modified_time as modified4_4_,
    todaytodo0_.deadline as deadline5_4_,
    todaytodo0_.delete_status as delete_s6_4_,
    todaytodo0_.room_id as room_id7_4_,
    todaytodo0_.todo_item as todo_ite8_4_,
    todaytodo0_.users_id as users_id9_4_,
    todaytodo0_.todo_status as todo_st10_4_ 
from
    todo todaytodo0_ 
where
    todaytodo0_.dtype='T' 
    and todaytodo0_.room_id=?
    and todaytodo0_.delete_status=? 
    and todaytodo0_.todo_status=?
    and (
        todaytodo0_.deadline between ? and ?
    ) 
order by
    todaytodo0_.created_time desc limit ?
table type key extra
todaytodo0_ ref todo_fk_room Using where;
Using filesort

 

생성시간을 역순으로 인덱스로 설정해 준다.

table type key extra
todaytodo0_ index todo_idx Using where

 

테스트하기

300명의 가상유저를 설정하고 시간은 5분으로 설정했다.

스레드를 초기화하는 부분에서 유저가 로그인을 하도록 했고

반복할일 생성하는 작업과 반복할일 조회하는 작업을 테스트했다. 

결과적으로 성능 지표라고 볼 수 있는 TPS가 1.72배 향상된 것을 확인할 수 있다.

적용 전
적용 후