[Book Review] 업무에 바로 쓰는 SQL 튜닝 2장 (1)

Noah·2022년 1월 26일
0

SQL 실행 원리

사용자는 DB에서 원하는 데이터를 가져오기 위해 SQL 문을 실행한다. 이때 파서(Parser)는 문법 에러가 있는지, DB에 존재하는 테이블인지 이러한 세부 사항을 다양한 문법 및 구문으로 검사한다. 이후 요청한 데이터를 빠르고 효율적으로 찾기 위한 전략적 계획을 수립하는데 이것은 옵티마이저(Optimizer)가 수행한다. 이 계획을 토대로 스토리지 엔진에 위치한 데이터를 찾아 MySQL 엔진으로 전달한다. MySQL 엔진은 전달된 데이터에서 불필요한 부분을 필터링하고 필요한 연산을 수행한 뒤 사용자에게 최종 결과를 알려준다.

스토리지 엔진

InnoDB, MyISAM 등과 같은 스토리지 엔진은 사용자가 요청한 SQL 문을 토대로 DB에 저장된 디스크에서 필요한 데이터를 가져오는 역할을 수행한다. 각 스토리지 엔진이 데이터를 저장하는 방식은 다르며 일반적으로 온라인상의 트랜잭션 발생으로 데이터를 처리하는 OLTP 환경이 대다수인 만큼 주로 InnoDB 엔진을 사용한다. 그 밖에도 대량 쓰기
트랜잭션이 발생하면 MyISAM 엔진을 사용한다.

MySQL 엔진

사용자가 작성한 SQL 문을 받아 문법 검사와 적절한 오브젝트 활용 검사를 하고 이후 스토리지 엔진으로부터 전달받은 데이터를 가공 및 연산하는 역할을 한다. 즉 SQL 문의 시작 및 마무리 단계에 관여한다.

  • Parser: MySQL 엔진에 포함되는 오브젝트로, 사용자가 요청한 SQL 문을 쪼개 최소 단위로 분리하고 트리를 만든다. 트리를 만들면서 문법 검사를 수행한다.

  • Preprocessor: 전처리기는 MySQL 엔진에 해당하는 오브젝트로, 파서에서 생성한 트리를 토대로 SQL 문에 구조적인 문제가 없는지 파악한다. 테이블, 칼럼, 함수, 뷰와 같은 오브젝트가 이미 생성된 오브젝트인지, 접근 권한은 부여되어 있는지 확인하는 역할을 한다.

  • Optimizer: MySQL 의 핵심 엔진 중 하나로, 인간에 비유하면 뇌의 역할을 한다고 할 수 있다. 전달된 파서 트리를 토대로 필요하지 않은 조건은 제거하거나 단순화한다. 나아가 어떤 순서로 테이블에 접근할지, 인덱스를 사용할지, 어떤 인덱스를 사용할지와 같은 실행 계획을 수립한다. 다만 옵티마이저가 예측한 모든 실행 계획이 항상 최적의 실행 계획은 아닐 수도 있다.

  • Engine executor: MySQL 엔진과 스토리지 엔진 영역 모두에 걸치는 오브젝트로, 옵티마이저에서 수립한 실행 계획을 참고하여 스토리지 엔진에서 데이터를 가져온다.


Index

데이터베이스에서 키값으로 실제 데이터 위치를 식별하고 데이터 접근 속도를 높이고자 생성되는, 키 기준으로 정렬된 오브젝트이다. 쉽게 설명하면 책에서 목차라고 할 수 있다. 목차를 통해 원하는 내용이 어디에 위치하고 있는지 쉽게 알 수 있고 쉽게 도달할 수 있다.

Unique Index

고유 인덱스란 말 그대로 인덱스를 구성하는 열들의 데이터가 유일하다는 의미이다. 다만 PK와 달리 Null 값을 허용한다.

Non-Unique Index

비고유 인덱스란 인덱스를 구성하는 열들의 데이터가 중복 값을 허용하는 인덱스이다.


Subquery

서브쿼리란 쿼리 안의 보조쿼리를 가리키는 용어이다.

Scalar Subquery

SELECT 절 내부에 존재하는 쿼리를 의미한다.

Inline View

FROM 절 내부에 작성한 서브쿼리를 인라인 뷰라 한다. 내부에서 일시적으로 뷰를 생성하는 방식이다. 때문에 내부적으로 메모리 또는 디스크에 임시 테이블을 생성하여 활용한다.

Nested Subquery

WHERE 절 내부에 작성한 서브쿼리로 중첩 서브쿼리라고 부른다.

Non Correlated Subquery

비상관 서브쿼리는 메인쿼리와 서브쿼리 간에 관계성이 없을을 의미한다. 서브쿼리가 독립적으로 실행된 뒤 메인쿼리에게 그 결과를 던져주는 형태인 것이다.

SELECT ... FROM Student WHERE IN (SELECT ... FROM Teacher)

즉, 비상관 서브쿼리는 서브쿼리가 먼저 실행된 뒤에 그 결과를 메인쿼리가 활용하는 형태이다.

Correlated Subquery

서브쿼리가 수행되려면 메인쿼리의 값을 받아야 하는 의존적인 관계를 의미한다.

SELECT * 
FROM 학생 
WHERE 학번 IN (SELECT 학번 
		FROM 지도교수 
        	WHERE 학생.학번 = 지도교수.학번) 

Single-Row Subquery

서브쿼리 결과가 1건의 행으로 반환되는 쿼리이다. 그에 따라 메인쿼리의 조건절에서는 비교 연산자와 비교하게된다. 또한 주로 스칼라 서브쿼리에도 사용된다.

SELECT ...
FROM ...
WHERE 학번 = (SELECT MAX(학번)
	     FROM 학생)

Multiple-Row Subquery

서브쿼리 결과가 여러 건의 행으로 반환되는 쿼리이다. 그에 따라 메인쿼리의 조건절에서는 IN 구문으로 서브쿼리에서 반환되는 값들을 활용할 수 있다.

SELECT ...
FROM ...
WHERE 학번 IN (SELECT MAX(학번)
	      FROM 학생
              GROUP BY 전공코드)

Multiple-Column Subquery

다중열 서브쿼리에서는 서브쿼리의 결과가 여러 개의 열과 행으로 반환된다. 즉 다중행 서브쿼리는 단일열에 다중행을 의미하지만 다중열 서브쿼리는 다중열 다중행의 결과를 반환하는 것이다.

SELECT ...
FROM ...
WHERE (이름, 전공코드) IN (SELECT 이름, 전공코드
	      		FROM 학생
              		WHERE 이름 LIKE '김%')
profile
개발 공부는 🌳 구조다…

0개의 댓글