SQL의 성능을 높이기 위해 처리범위를 설정하는 것이 관건이다.
Why? 쿼리유형에 따라 성능 및 부하가 많이 차이날수 있기 때문이다.
기본적으로 튜닝을 하려면 통계정보/인덱스/쿼리호출방식/서비스유형 등이 연계되어 있는 부분이라 에 대해서 공부하여 검토해야한다. (단순히 쉽게 특정 조건만 넣거나 힌트제어를 한다고 빨라지는게 아니라서...)
그래도 몇가지 큰 틀은 있으니 함께 살펴보자!
대부분의 SQL 속도 저하는 SELECT와 WHERE 조건절에서 발생하는데,
오늘은 SELECT, WHERE 절에서 성능을 높일 수있는 2가지 조건을 살펴본다
1. 점조건 : IN, =
점조건이 성능개선에 도움이 된다. 그래서 선분조건이더라도 점조건으로 바꿔서 호출하는경우가 많다
2. 선분조건(범위조건) : Between, like, <, >
INDEX(인덱스)란?
DB 테이블에 대한 검색 성능 속도를 올려주는 자료 구조.
→ 인덱스에서 원하는 데이터를 먼저 찾고 해당 물리적 주소로 찾아감 (책의 '목차', 에버랜드의 '지도')
Tip. Cardinality가 높은 칼럼에 INDEX 생성하는 것이 유리
Cardinality란?
전체 데이터의 유니크 수 ex) '고객번호'칼럼이 '성별'칼럼보다 cardinality가 높다
인덱스 장점
1. ORDER BY 효율성: 인덱스를 사용하면 order by 의 sort 과정을 안해도된다.
→ ORDER BY는 부하가 굉장히 많이 걸리는 작업인데 index를 통해 이를 안해도 됨
2. MIN, MAX 효율성 : 1의 이유로 데이터가 이미 정렬되어있어, MIN, MAX 가 처음과 끝값이기에
처리범위를 감소시키는 효율적인 쿼리
1. 선분조건을 점조건으로 바꾼다
* NOT IN(선분조건) → IN(점조건) 으로 효율적인 인덱스 활용/스캔을 유도하여 성능 개선
2. 점조건(IN, = 연산자) 먼저 기술 → 선분조건 (LIKE, BETWEEN, <, > ) 기술
3. 1순위 INNER JOIN, 점조건(IN, =) -> inner join 은 1:1 조인방식, 점조건은 단일조건 검색
2순위 LEFT/RIGHT/FULL OUTER Join 은 1:다, 다:1, 다:다 등으로 처리 범위가 커지기 때문에 안좋음
선분조건도 범위가 커져서 안좋음
* user_id 컬럼에 A,B,C,D 데이터가 각각 존재하는데
WHERE user_id NOT IN ('A','B','C') -- 으로 호출할 시에
WHERE user_id IN ('D') -- 로 바꿔서 호출하는 방식으로
<유의할 점>
A,B,C,D 말고 다른 유형의 데이터가 더들어오면 IN조건의 쿼리에 해당 데이터를 추가해줘야 하기 때문에
데이터 유형이 추가되는경우 까먹지말고 쿼리소스를 수정 필수.
세가지 쿼리 예제를 살펴보면서 성능이 좋은 쿼리를 작성해보는 연습을 해보자!(아래 3개 쿼리는 동일한 쿼리이다)
쿼리 작성시 유의사항
- 실제 성능 비교는 '실행계획'을 보고 판단할수있다(처리 속도, 실제 컴퓨터에서 처리하는 쿼리)
- 하나의 쿼리로 다양한 유형의 쿼리를 작성할수 있는데 보통 최대 11가지 유형까지 만들 수있다
- LEFT.JOIN을 할때 main table은 데이터 용량이 큰 테이블로 한다
- 보기 쉽고, 짧은 쿼리도 좋으나, 그보다 더 중요한 건 검색을 최소화 할 수 있는 쿼리가 좋다
- 쿼리 2의 WHERE IN 조건의 경우 DB에서 자체적으로 조인형식으로 풀어서 호출하기때문에 쿼리1 과 내부적으로 동일하게 풀릴거라 성능이나 부하 차이는 없다
→ 사용자는 WHERE IN 조건으로 호출해도 DB내부적으로는 조인형식으로 변경하여 호출
쿼리1
쿼리 1의 경우 from 절 안에 inner join 을 넣었는데, 이렇게 하는 경우는 드물다고함
# 쿼리 1
SELECT COUNT(1) AS CNT
FROM
(SELECT user_id, IS_SMS FROM DB.TB_1 WHERE AAA = 1) AS A
INNER JOIN DB.TB_2 AS B
(ON A.user_id = B.user_id)
WHERE B.CONDITION = 'N'
쿼리2
쿼리 2의 경우, 4번째 줄에 보면 user_id를 IN절 1) 안에서 한번 찾고, 2) 밖에서 또 한번 찾으니깐 아무래도 두번 찾게 만드는건 별로 좋지 않다.
IN 조건 = 조건 써서 점조건 사용
# 쿼리 2
SELECT COUNT(DISTINCT user_id)
FROM DB.TB_1
WHERE AAA = 1
AND user_id IN (SELECT user_id FROM DB.TB_2 WHERE CONDITION ='N')
쿼리 3
쿼리 3의 경우, main table에서 inner join을 하고, WHERE 조건에서 점조건으로 2개를 조건 넣었다!
# 쿼리 3
SELECT COUNT(1) AS CNT
FROM DB.TB_1 AS A
INNER JOIN DB.TB_2 AS B
(ON A.user_id = B.user_id)
WHERE A.AAA = 1
AND B.CONDITION = 'N'
※ 참고 : DB튜닝 및 내부 처리방식
- JOIN도 세부적으로 들어가면 1:1로 비교하는 점조건 방식이라 내부처리방식은 동일
- 실행계획 : 튜닝으로 들어가게되면 HASH JOIN / NL JOIN / MERGE JOIN 등이 있는데 우리가 겉으로 보여지는 호출되는 쿼리외적으로 쿼리가 내부에서 어떻게 풀리는지 실행계획을 볼수있는데 실행계획에서 어떤방식으로 풀리냐고 중요해요
- 실행계획 확인하는 곳 : 따로 DB툴이나 DB서버에 들어가서 봐야되요
- 옵티마이저 : DB내에 뇌역할을 하는 옵티마이저가 자기가 알아서 판단해서 쿼리도 내부적으로 변형해서 실행
- 옵티마이저가 가끔 잘못해석해서 수행하는경우 부하 및 성능에 이슈가 생겨서 전문튜너가 강제로 효율적인 방식으로 변경하기도 함
'SQL' 카테고리의 다른 글
[SQL] update, set - 테이블 내 데이터 값 변경하기 (0) | 2022.08.30 |
---|---|
Mysql 에 csv 파일 불러오기 (0) | 2022.08.15 |
hackerrank (0) | 2022.06.27 |
실무 SQL 예제 2 (0) | 2022.06.27 |
실무 SQL 예제 (0) | 2022.06.27 |