BACKEND/SpringBoot

MSSQL, Mybatis :: DB툴과 웹에서의 쿼리 속도가 다를 때 고려할 것

neeon 2024. 1. 16. 11:16
728x90

 

쿼리속도는 00:00:06 초 정도로 짧게 나오는데

API 실행 속도는 48초가 나오는 케이스가 발생.

 

물론 건 수가 많은 SQL이기는 했지만,

쿼리 속도와 API 속도가 이렇게 비례하지 않는 케이스는 처음이었음.

 

-- 이런 현상이 발생하는 경우는 대부분 Where 절의 조건이 VARCHAR로 되어 있다는 것

 

MSSQL 의 특징

MSSQL의 경우 VARCHAR형 데이터를 비교할 때 NVARCHAR형으로 변환하여 데이터를 비교한다고 함.

즉, 데이터의 사이즈를 가변으로 할지 아닐지를 결정하는 것으로 보임.

쿼리를 사용할 때마다 강제적으로 타입 캐스팅이 일어나고, 수행되는 쿼리의 타입이 다르기 때문에 INDEX를 안타게 됨.

ㅠ-ㅠ.. 쿼리 튜닝을 아무리해도 DB 속도는 빨라지는데, API 호출 속도는 크게 차이가 나지 않는 이슈

 

Mybatis의 특징

 

마이바티스에서 값을 불러오는 방식은 ${}와 #{} 두가지가 있다.

 

 

Mybatis :: 달러($)와 샵(#)의 차이

파라미터 매핑을 하는 데에 사용하는 $와 # 두가지의 차이에 대해 알아보도록 하겠다. # PreparedStatement를 의미 파라미터가 String 형태로 들어와 자동으로(' ') 파라미터 형태가 됨 #{user_id} 의 값이 'n

bornatnoon.tistory.com

 

차이는 PreparedStatement 라는 것과, Statement 라는 것의 차이가 있는데..

대부분 Preparedstatement가 쿼리를 미리 생성하고 데이터를 넣기 때문에 성능에 유리하다고 알고 있음..

 

보통 그게 맞는 말이지만, Statement에도 장점이 있기 때문에 기능을 분리해서 사용하면 성능 향상에 도움이 된다.

 

변경

 

1. 파라메터 방식 수정

SELECT * FROM table WHERE id LIKE '%' + '${value}' + '%'

 

기존에 #{} 으로 받아오던 방식에서 ${} 으로 받아오도록 방식을 수정해본다.

 

결과: 쿼리 속도와 API 호출 속도가 같아짐

 

하지만 이렇게 방식을 바꾸게 되면 SQL Injection을 방지할 방법을 Service 나 Controller 단에 추가 해줘야 한다. 꼭.

추후에 보안 문제가 발생할 수 있기 때문.

 

2. 강제로 타입 변환 Typecasting

SELECT * FROM table WHERE name  =  CAST( #{value} AS VARCHAR)
SELECT * FROM table WHERE  name = CONVERT(VARCHAR(10), #{value})

 

원하는 방식으로 타입 변환을 해주면 된다.

 

여기에 추가하여 옵티마이저를 끄도록 한다. 룰 베이스로 변경하도록 해보자.

select /*+ RULE */
      e.empno,
          e.ename,
          d.dname
from  dept d, emp e
where  e.deptno = d.deptno;

 

이렇게 변경하면, 쿼리 계산 속도도 줄고 하니.. API 호출 속도도 줄기는 하는데

파라메터 받는 방식을 변환한 것 보다는 속도가 딸리기는 한다.

 

원래의 API 호출 시간이 한 58초 정도 걸렸다면, 위의 방법으로 바꿀 시에는 43초 정도 뜨는 정도?

보안이나 기존 코딩 룰을 지키면서 튜닝하기에는 해당 방법이 적합하지만 아직 속도 개선 부분에서는 부족한 모습.

 

--

 

우리의 케이스에서는 우선

성능이 저하되는 조회와 관련된 부분에서만 ${}을 사용하는 것을 임시 방책으로 지정해둔 상태.

 

정확한 방법으로 변경이 필요하긴 할 것 같다..

 

 

 

728x90