본문 바로가기

프로젝트/고민

성능 최적화 (스케일 업, 인덱스 튜닝)

목표 TPS

저번 글에서 시나리오를 통해 성능테스트를 진행해봤다. TPS는 13이 나왔고 목표했던 17 ~ 52에 한참 모자란 결과이다.

예상보다 TPS가 너무 나오지 않아 원인을 분석해본 결과 DB인 것으로 확인이 됐다. 그래서 팀원끼리 각자 맡은 도메인에 대해 쿼리를 개선해보기로 하고 다시 성능테스트를 해봤다. DB에 데이터는 10만건 들어있는 상태다.

 

먼저 시나리오에 포함되지 않은 읽기 쿼리들까지 포함해서 성능테스트를 해본 결과 다음과 같은 결과가 나왔다.

 

에러율은 낮지만 TPS는 4.7로 처참한 것을 확인할 수 있다.

 

db는 RDS의 t3.micro를 사용하고 있었는데, cpu 사용량이 100퍼센트 가까히 찍히는 것을 확인할 수 있다.

 

 

단순히 인덱스 튜닝만으로는 해결할 수 없을 정도의 TPS와 RDS의 CPU 사용량이라고 판단이 들어 먼저 스케일 업을 했다.

스케일 업

t3.micro -> t4.small로 스케일업 한 결과 

 

tps는 올랐지만 여전히 낮은 상태이다. 그래도 인덱스 튜닝을 하면 성능이 꽤 오를 것 같다고 생각이 들어 인덱스를 태워봤다.

인덱스 튜닝

SELECT 
    question.id,
    question_form.question_content
FROM 
    question
INNER JOIN 
    question_form ON question.question_form_id = question_form.id
WHERE 
    question.couple_id=1 AND
    question.boy_choice_index <> 0 AND
    question.girl_choice_index <> 0    
    -- AND question.id < 10000
ORDER BY 
    question.id DESC
LIMIT 10;

 

병목이 된다고 생각이 드는 쿼리는 위와 같았고, 실행계획은 아래와 같다.

 

type 도 ref, eq_ref로 동등 조건에 의한 검색이기 때문에 좋아보여 어떤 것이 문제인지 더 파악하기 위해 쿼리를 analyze 키워드로 다시 실행해봤다.

 

위 실행계획을 보니 nested loop를 하는데, 40931건의 row를 읽는다고 적혀있다. 한마디로 where 조건 중 첫번째 조건을 index로 읽고 다음 조건부터 이중 포문을 도는 것 처럼 읽는다고 해석이 된다. 이러한 경우 where 조건의 순서대로 index를 걸어버리면 성능이 확 개선된다고 예상이 됐기 때문에 그렇게 인덱스를 걸고 실행계획을 확인해봤다.

couple_id, boy_choice_index, girl_choice_index 컬럼에 복합 인덱스를 걸고 쿼리 실행계획을 확인하니 아래와 같다.

 

튜닝 후

 

정말 운이 좋게도 2개의 row를 읽도록 성능이 훨씬 계선되었다. 정렬할 때 filesort가 표시가 된 것을 보아 인덱스로 정렬을 하지 못하지만, 읽는 row의 수가 매우 적으므로 성능은 많이 개선됐다고 본다.

 

실제로 쿼리의 분석 내용도 한번의 row에 대해 nested loop join을 한다.

 

튜닝 후 성능테스트 결과

 

TPS도 2배 넘게 오른 것을 확인할 수 있다. 아직 목표 TPS에 비해 턱 없이 부족하지만, 개선이 많이 됐다.

비용

스케일 업과, 인덱스 튜닝을 하며, 초당 트랜잭션 수(TPS)를 4.7에서 17.5까지, 약 4배 향상시켰다. 비록 스케일 업으로는 월 서버 비용이 $18.25에서 $37.25로 증가했지만, 성능은 두 배 이상 개선되었다. 추가적으로, 데이터베이스 인덱스 튜닝은 추가 비용 없이 진행되었고, 이를 통해 성능이 많은 성능 개선이 이루어졌다. 결과적으로, 스케일 업으로 인한 비용 증가는 있었지만, 인덱스 튜닝으로 인한 성능 향상은 비용을 들이지 않고 이뤄졌기 때문에, 인덱스 튜닝을 통해 얻은 가치는 최소 18달러 이상은 된다고 볼 수 있다.