SQL 개발자 자격증
회차 | 원서 접수 | 수험표 발급 | 시험일 | 사전점수 공개 및 재검수 접수 | 합격자 발표 |
---|---|---|---|---|---|
제58회 | 7.21~25 | 8.8 | 8.23(토) | 9.12~16 | 9.19 |
docker run -d \
--name oracle-xe \
-p 1521:1521 -p 8080:8080 \
-e ORACLE_ALLOW_REMOTE=true \
-e ORACLE_PASSWORD=oracle \
gvenzl/oracle-xe
docker exec -it oracle-xe sqlplus system/oracle@//localhost:1521/XE
docker run --name mysql8.4 \
-e MYSQL_ROOT_PASSWORD=yourpassword \
-e MYSQL_DATABASE=testdb \
-p 3306:3306 \
-d mysql:8.4
docker exec -it mysql8.4 mysql -uroot -pyourpassword
MySQL의 아키텍처
MySQL의 아키텍처를 간단하게 표현하자면 위와 같다. 이 아키텍처에서 SQL문이 어떻게 실행되는 지 과정을 알아보자.
- 클라이언트가 DB에 SQL 요청을 보낸다.
- MySQL 엔진에서 옵티마이저가 SQL문을 분석한 뒤 빠르고 효율적으로 데이터를 가져올 수 있는 계획을 세운다. 어떤 순서로 테이블에 접근할 지, 인덱스를 사용할 지, 어떤 인덱스를 사용할 지 등을 결정한다. (옵티마이저가 세운 계획은 완벽하지 않다. 따라서 SQL 튜닝이 필요하다.)
- 옵티마이저가 세운 계획을 바탕으로 스토리지 엔진에서 데이터를 가져온다. (DB 성능에 문제가 생기는 대부분의 원인은 스토리지 엔진으로부터 데이터를 가져올 때 발생한다. 데이터를 찾기가 어려워서 오래 걸리거나, 가져올 데이터가 너무 많아서 오래 걸린다. SQL 튜닝의 핵심은 스토리지 엔진으로부터 되도록이면 데이터를 찾기 쉽게 바꾸고, 적은 데이터를 가져오도록 바꾸는 것을 말한다.)
- MySQL 엔진에서 정렬, 필터링 등의 마지막 처리를 한 뒤에 클라이언트에게 SQL 결과를 응답한다.
SQL 튜닝의 핵심
자, 다시 한 번 정리하자. SQL 튜닝에 있어서 핵심은 2가지이다.
- 스토리지 엔진에서 데이터를 찾기 쉽게 바꾸기
- 스토리지 엔진으로부터 가져오는 데이터의 양 줄이기
인덱스(Index)란?
인덱스의 정의를 찾아보면 아래와 같다.
인덱스(Index)는 데이터베이스 테이블에 대한 검색 성능의 속도를 높여주는 자료 구조를 뜻한다.
위의 정의보다는 아래의 의미로 인덱스를 기억하자. 그래야 훨씬 직관적으로 이해하기가 쉽다.
인덱스(Index) : 데이터를 빨리 찾기 위해 특정 컬럼을 기준으로 미리 정렬해놓은 표
참고로 실제 DB에서는 인덱스를 생성한다고 해서 정렬된 표를 직접 눈으로 확인할 수는 없다. 시스템 내부적으로 생성될 뿐이다.
원본 데이터 자체가 정렬되는 인덱스를 보고 클러스터링 인덱스라고 부른다. PK(Primary Key) = 클러스터링 인덱스라고 생각해도 된다. 클러스터링 인덱스는 PK(Primary Key) 밖에 없기 때문이다.
MySQL은 UNIQUE 제약 조건을 추가하면 자동으로 인덱스가 생성된다
인덱스를 사용하면 데이터를 조회할 때의 성능이 향상된다. 그러면 인덱스를 무조건적으로 많이 추가하는 게 좋다고 착각할 수도 있다. 하지만 인덱스를 추가하면 조회 성능은 올라가지만, 쓰기 작업(삽입, 수정, 삭제)의 성능은 저하된다.
멀티 컬럼 인덱스란, 2개 이상의 컬럼을 묶어서 설정하는 인덱스를 뜻한다. 즉, 데이터를 빨리 찾기 위해 2개 이상의 컬럼을 기준으로 미리 정렬해놓은 표이다.
CREATE INDEX idx_age ON users(age);
CREATE INDEX idx_부서_이름 ON users (부서, 이름);
멀티 컬럼 인덱스를 만들어두면 일반 인덱스처럼 활용할 수 있다.
하지만 멀티 컬럼 인덱스를 일반 인덱스처럼 활용하지 못하는 경우도 있다.
위에서 부서
, 이름
순으로 멀티 컬럼 인덱스를 만들어뒀기 때문에, 부서
컬럼의 인덱스를 만든 것과 같은 역할도 같이 수행한다고 했다. 하지만 이 멀티 컬럼 인덱스로는 이름
컬럼의 인덱스처럼 활용할 수는 없다.
따라서 멀티 컬럼 인덱스에서 일반 인덱스처럼 활용할 수 있는 건 처음에 배치된 컬럼들뿐이다.
멀티 컬럼 인덱스를 구성할 때 ‘소분류 → 중분류 → 대분류’ 컬럼순으로 구성하기
멀티 컬럼 인덱스를 만들 때는 순서에 주의해야 한다. 왜냐하면 순서를 어떻게 정해서 인덱스를 만드느냐에 따라서 성능 차이가 나기 때문이다.
먼저 직관적으로 이해해보자. 대기업에서 회계 부서
의 박미나
를 찾아야 한다고 가정하자. 회계 부서
의 모든 인원을 만나본 뒤에 박미나
를 찾는게 빠를까? 아니면 박미나
라는 이름을 가진 동명이인 사람들한테 직접 찾아가서 회계 부서
인지를 물어보는 게 빠를까?
일반적으로 회계 부서
의 인원보다 박미나
라는 이름을 가진 인원이 훨씬 적기 때문에, 박미나
를 먼저 찾은 뒤에 회계 부서
인지를 물어보는게 빠를 것이다. 이를 일반화해서 표현하자면 ‘소분류를 먼저 탐색한 뒤, 대분류를 탐색하는 게 빠르다.‘라고 할 수 있다. 컴퓨터도 이 특성이 동일하게 적용된다.
멀티 컬럼 인덱스에서도 배치한 컬럼의 순서대로 데이터를 탐색한다. (이름, 부서)
의 순서대로 멀티 컬럼 인덱스를 구성했다면 먼저 일치하는 이름
을 찾은 뒤, 일치하는 이름
에서 부서
를 찾는 식으로 처리한다.
따라서 멀티 컬럼 인덱스를 구성할 때는 데이터 중복도가 낮은(≒ 카디널리티가 높은) 컬럼이 앞쪽으로 오는 게 좋은 경우가 많다. (항상 그런 건 아니니 실행 계획과 SQL문 실행 속도를 측정해서 판단하도록 하자.)
커버링 인덱스(Covering Index)란?
SQL문을 실행시킬 때 필요한 모든 컬럼을 갖고 있는 인덱스를 커버링 인덱스(Covering Index)라고 한다.
ROLLUP vs GROUPING SETS vs CUBE 비교표
항목 | ROLLUP | GROUPING SETS | CUBE |
---|---|---|---|
기본 목적 | 계층적 소계/총계 자동 생성 | 원하는 조합만 수동 지정 | 가능한 모든 조합 자동 생성 (다차원 집계) |
조합 생성 방식 | 왼쪽부터 오른쪽으로 점진적 축소 | 사용자가 지정한 조합만 생성 | 모든 컬럼 조합의 파워셋 생성 |
유연성 | 제한적 | 가장 유연함 | 중간 정도 |
NULL 의미 | 생략된 그룹화 컬럼 | 생략된 컬럼에 대해 NULL 처리 | 동일 |
예시 입력 | ROLLUP(a, b) |
GROUPING SETS ((a, b), (a), (b), ()) |
CUBE(a, b) |
결과 조합 수 | 3개 → (a,b), (a), () | 4개 → (a,b), (a), (b), () | 4개 → (a,b), (a), (b), () |
(a, b) 조합 포함 여부 | ✅ | ✅ | ✅ |
(a) 단독 조합 포함 여부 | ✅ | ✅ | ✅ |
(b) 단독 조합 포함 여부 | ❌ | ✅ | ✅ |
() 총합 포함 여부 | ✅ | ✅ | ✅ |
주요 사용 목적 | 보고서/소계/총계 | 맞춤형 보고서 조합, 성능 제어 | OLAP/피벗 등 다차원 분석 |
SQLD 출제 빈도 | 높음 | 중간 | 낮음 |
- SQL 전문가 가이드
- SQL 자격능력 검정 실전문제
- 친절한 SQL 튜닝
- 오라클 성능 고도화 원리와 해법 1
- 오라클 성능 고도화 원리와 해법 2
- SQLP 핵심노트 1
- SQLP 핵심노트 2