수 많은 우문은 현답을 만든다

쿼리 성능테스트에서 발견한 CPU 100% 이슈 해결 본문

개발지식/Database(DB)

쿼리 성능테스트에서 발견한 CPU 100% 이슈 해결

aiden.jo 2022. 12. 23. 17:31

안녕하세요 조영호입니다.

오늘은 성능테스트 당시 발견한 CPU 사용률이 100%까지 올라가는 현상을 해결한 경험을 공유하고자 합니다.

다른 웹 페이지들과는 다르게 빅데이터(약 80,000,000건)를 조회하는 페이지에서 TPS가 너무 낮게 나오는 현상이 있었습니다.

 

이슈 내용

  • Database 조회 Table에는 적절한 Index를 설정했다
  • 조회 API에서 Index 검색을 탈 수 있도록 필요한 컬럼들을 파라미터로 보냈다
  • 동시접속자 30명이 넘어가면 CPU가 100%를 치면서 서비스가 마비되는 현상이 발생했다. 

 

테스트 내용

Jmeter로 동시 접속 사용자를 기준으로 웹 사이트의 부하테스트를 수행했습니다.
일반적으로 데이터가 많지 않은 Back-end API는 호출시 300 tps 이상의 빠른 응답을 보였지만, 빅데이터 조회 페이지의 경우 TPS가 10 미만인 결과를 보였습니다.

  동시 접속자 수 평균 TPS
로그인 페이지 1,000 417
3,000 532
일반 조회 페이지 1,000 311
3,000 314
빅데이터 조회 페이지 1,000 7
3,000 8

 

원인 파악

  • DB 서버가 4 core 를 사용하는데 자원이 부족한가?
    -> 4 core 가 작다고 생각할 수도 있지만, 다른 요청들을 처리할때는 10% 미만의 사용률을 보였기 때문에 쿼리 문제로 생각했다.

  • 쿼리 튜닝, 종합적인 이력을 보여주는 페이지라서 JOIN 이 네번정도 들어가는데 이 때문일까?
    - 서브쿼리를 제거하고 명시적 조인 조건을 사용하도록 개선
    - 테스트를 위해 조인들을 제거했으나 계속 CPU 100% 를 점유

  • 인덱스 설정이 부족한가?
    - 검색시 인덱스 조회를 하기 위해서, 인덱스가 걸린 조건들로만 조회를 했지만 그래도 CPU 100% 를 점유

  • 애플리케이션 <->  DB 구간의 특이점이 있을까?
    - Java Back-end 에서는 날짜를 DateTime으로 관리하고 있는데, DB 관리자가 날짜 타입을 String으로 저장하고 있음을 발견했다.
     ㄱ. 이와 같은 경우 Oracle DB 에서는 문자열이 날짜타입으로 변화하는 작업이 생겨 부하가 발생한다.
     ㄴ. 타입 변환이 발생하면 불운하게도 인덱스를 타지 않고 Full-text search 가 발생해 속도 저하가 발생한다.
     ㄷ. 그래서 Java Back-end 의 날짜 타입을 String으로 변환했는데 그래도 여전히 CPU 100% 를 점유했다.

  • 놓친 부분은 없는가?
    - String 타입으로 통일했음에도 불구하고 인덱스를 타지 않아서 쿼리에 문제가 있다고 확신했다.
    - 이 사건의 핵심 원인은 BETWEEN 구문에 있었다.
          ex. BETWEEN '20230101' AND '20230131'
     - 위 구문에서는 String 과 String 을 비교하므로, 매 연산마다 문자열을 날짜로 변환하는 작업이 발생했고 그래서 인덱스를 타지 않는 것이다. 엄청난 부하가 여기서 발생했다.
     
  • 개선 방법
    1) 애플리케이션과 DB 구간에서 DateTime 타입을 쓰는 방법
    2) 날짜데이터를 문자열에서 DateTime으로 바꿔주거나 날짜 구간을 설정해 IN 검색을 사용하는 방법
       ex. date IN ( 1, 2, 3, 4, 5, 6, 7) 

 

개선 결과

  동시 접속자 수 평균 TPS
빅데이터 조회 페이지 1,000 7 -> 334
3,000 8 -> 380

 

항상 문제의 원인은 알고나면 별 것 아니다.
여러 개발자와 함께하는 프로젝트에서 다양한 문제의 원인을 찾는 과정은 어렵지만 재밌다.   

'개발지식 > Database(DB)' 카테고리의 다른 글

Mybatis Cash  (0) 2023.03.03