DB

DB 성능차이에 대한 Tips

Dream Herb 2023. 7. 29. 22:36

 

DB 성능을 조정하기 위한 여러가지 꿀팁들이 있겠지만 여기서 한 번 최대한 정리해보려한다.

 

1. 서브쿼리보다 join을 이용하는 것이 보통 더 빠르다!

 

그래서 보통 서브쿼리랑 JOIN문이 같이 있는 쿼리의 경우 더 빨리 끝나는 JOIN을 먼저 처리하고 서브쿼리는

나중에 처리하는 것이 좋다고 한다.

# 예시
select  
	a.*  # 더 빨리 나오는 JOIN문을 먼저 처리하였다.
    , (SELECT count(*) test FROM testDB WHERE a.id = b.id)
    # 이렇게 생긴 것이 서브쿼리 
from
(SELECT
	테이블1,컬럼1,
	테이블2,컬럼2,
	테이블3,컬럼3,
...
FROM
	테이블1
join 테이블2 # 조인문
	on 테이블1.컬럼1 = 테이블2.컬럼2
join 테이블3
	on 테이블1.컬럼1 = 테이블3.컬럼3
) a

 

[서브쿼리란?]

외부 쿼리(메인 쿼리) 내부에 있는 내부쿼리, 쿼리안에 쿼리가 들어간 것

서브쿼리 만으로 연산이 가능한 경우가 있고 서브쿼리가 메인쿼리의 열에 의존하는 경우가 있다.

 

물론 모든 경우에 사용할 수는 없겠지만 아래와 같은 경우에선 사용해볼 수 있을 것이다!

예시를 통해 알아보자

 

ex)

테스트를 위한 가벼운 생성문

CREATE TABLE test.Student ( id INT PRIMARY KEY NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, class_id INT NOT NULL);
CREATE TABLE test.Class (
    id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL
);
INSERT INTO test.Student (id, name, class_id)
VALUES (1, '알렉스', 1), (2, '듀크', 3);
INSERT INTO test.Class (id, name)
VALUES (1, '생물학'), (2, '지리학'), (3, '수학');

 

Student 테이블

id name class_id
1 알렉스 1
2 듀크 3

 

Class 테이블

id Name
1 생물학
2 지리학
3 수학

 

학생들이 듣고있는 강의의 이름을 알고 싶은 경우

서브쿼리:

SELECT name
FROM test.Class
WHERE test.Class.id = (
SELECT class_id FROM test.Student WHERE test.Class.id = test.Student.class_id
);

연산 결과는 다음과 같다.

 

name
생물학
수학

서브쿼리는 직관적이지만 메인쿼리의 id(class의 id)와 서브쿼리의 id(Student의 class_id)를 매칭해주는 작업을 위해

class의 id 개수만큼 서브쿼리가 실행되므로 메인쿼리의 수가 많다면 효율적이지 못하다고 할 수 있다.

그래서 이런 경우엔 JOIN을 사용하는 것이 효율적이라고 한다.

 

JOIN:

SELECT c.name
FROM test.Class AS c
JOIN test.Student AS s
ON c.id = s.class_id;

 

Plus) 문득 궁금해서 각각의 학생들이 어떤 강의를 듣는지 출력해보려 했다.

JOIN을 쓸 경우

SELECT c.name, s.name
FROM test.Class AS c
JOIN test.Student AS s
ON c.id = s.class_id;

결과는 다음과 같다

name name
생물학 알렉스
수학 듀크

 

그런데 위 JOIN을 사용한 쿼리문을 JOIN없이 서브쿼리로 대체할 수는 없는 걸까?

궁금해서 아래와 같은 쿼리문을 시도해보았다.

SELECT c.name, 
       (SELECT name
        FROM test.Student s
        WHERE s.class_id = c.id) AS student_name
FROM test.Class c;

하지만 그 결과는 다음과 같았다.

name name
생물학 알렉스
지리학 null
수학 듀크

이는 어쨌든 Class의 모든 네임에 대해 서브쿼리를 실행하므로 '지리학'의 경우엔 null 값이 나오는 것이다.

이 쿼리를 어떻게 손보고 있지만 아직 찾지 못해 추후 좀 더 찾아보아야겠다.

 

 

출처:

 

https://kimsyoung.tistory.com/entry/%EC%84%9C%EB%B8%8C-%EC%BF%BC%EB%A6%AC%EC%9D%98-%EC%A2%85%EB%A5%98%EC%97%90%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B4-%EC%9E%88%EC%9D%84%EA%B9%8C

https://kimsyoung.tistory.com/entry/SUBQUERY-%EC%99%80-JOIN-%EC%9D%98-%EC%B0%A8%EC%9D%B4-%E4%B8%8A

https://www.w3schools.com/sql/sql_join_left.asp