MySQL 성능 최적화
28,000원
고급
도서 소개
MySQL 서버를 활용하는 프로젝트에 꼭 필요한 경험과 지식을 담았습니다!
《Real MySQL 8.0》은 《Real MySQL》을 정제해서 꼭 필요한 내용으로 압축하고, MySQL 8.0의 GTID와 InnoDB 클러스터 기능들과 소프트웨어 업계 트렌드를 반영한 GIS 및 전문 검색 등의 확장 기능들을 추가로 수록했다.
또한 《Real MySQL 8.0》은 단순 SQL 문법이나 쿼리 작성보다는 MySQL 서버를 활용하는 프로젝트에서 꼭 필요한 경험과 지식을 전달하는 데 집중했다.
이 책을 처음부터 끝까지 정독할 수 있다면 더없이 좋겠지만 필요하거나 관심 있는 내용 위주로 살펴봐도 지금까지 경험했던 수많은 문제들을 해결할 수 있을 것이다.
★ 이 책에서 다루는 내용 ★
- MySQL 설치와 서버 아키텍처
- 트랜잭션과 잠금
- 인덱스 종류의 구조 및 활용
- GTID 기반 복제 및 InnoDB 클러스터 아키텍처
- 쿼리의 실행 계획 분석 및 최적화
- 스토어드 프로그램 개발
- 데이터 모델링 및 최적의 데이터 타입 선정
- 파티션 및 데이터 압축 활용
- GIS 및 전문 검색 기능 활용
- Performance 스키마 및 Sys 스키마 활용
도서 상세 이미지

저자 소개
백은빈
컴퓨터 공학을 전공하고 카카오에서 MySQL/MongoDB DBA로 근무하면서 DB 운영 및 트러블슈팅과 데이터 모델링, DBMS 도구 개발 및 신기술 벤치마킹을 수행했으며, 현재 당근마켓에서 MySQL/MongoDB DBA로 근무하고 있다.
이성욱
컴퓨터 과학을 전공하고 네이버와 라인을 거쳐 카카오 및 밸런스히어로에서 DBA로 근무했으며, 현재 당근마켓 DB팀 리더로 근무하고 있다.
목차
- ▣ 11장: 쿼리 작성 및 최적화
- 11.1 쿼리 작성과 연관된 시스템 변수
- 11.1.1 SQL 모드
- 11.1.2 영문 대소문자 구분
- 11.1.3 MySQL 예약어
- 11.2 매뉴얼의 SQL 문법 표기를 읽는 방법
- 11.3 MySQL 연산자와 내장 함수
- 11.3.1 리터럴 표기법 문자열
- 11.3.2 MySQL 연산자
- 11.3.3 MySQL 내장 함수
- 11.4 SELECT
- 11.4.1 SELECT 절의 처리 순서
- 11.4.2 WHERE 절과 GROUP BY 절, ORDER BY 절의 인덱스 사용
- 11.4.3 WHERE 절의 비교 조건 사용 시 주의사항
- 11.4.4 DISTINCT
- 11.4.5 LIMIT n
- 11.4.6 COUNT()
- 11.4.7 JOIN
- 11.4.8 GROUP BY
- 11.4.9 ORDER BY
- 11.4.10 서브쿼리
- 11.4.11 CTE(Common Table Expression)
- 11.4.12 윈도우 함수(Window Function)
- 11.4.13 잠금을 사용하는 SELECT
- 11.5 INSERT
- 11.5.1 고급 옵션
- 11.5.2 LOAD DATA 명령 주의 사항
- 11.5.3 성능을 위한 테이블 구조
- 11.6 UPDATE와 DELETE
- 11.6.1 UPDATE ... ORDER BY ... LIMIT n
- 11.6.2 JOIN UPDATE
- 11.6.3 여러 레코드 UPDATE
- 11.6.4 JOIN DELETE
- 11.7 스키마 조작(DDL)
- 11.7.1 온라인 DDL
- 11.7.2 데이터베이스 변경
- 11.7.3 테이블 스페이스 변경
- 11.7.4 테이블 변경
- 11.7.5 칼럼 변경
- 11.7.6 인덱스 변경
- 11.7.7 테이블 변경 묶음 실행
- 11.7.8 프로세스 조회 및 강제 종료
- 11.7.9 활성 트랜잭션 조회
- 11.8 쿼리 성능 테스트
- 11.8.1 쿼리의 성능에 영향을 미치는 요소
- 11.1 쿼리 작성과 연관된 시스템 변수
- ▣ 12장: 확장 검색
- 12.1 전문 검색
- 12.1.1 전문 검색 인덱스의 생성과 검색
- 12.1.2 전문 검색 쿼리 모드
- 12.1.3 전문 검색 인덱스 디버깅
- 12.2 공간 검색
- 12.2.1 용어 설명
- 12.2.2 SRS(Spatial Reference System)
- 12.2.3 투영 좌표계와 평면 좌표계
- 12.2.4 지리 좌표계
- 12.1 전문 검색
- ▣ 13장: 파티션
- 13.1 개요
- 13.1.1 파티션을 사용하는 이유
- 13.1.2 MySQL 파티션의 내부 처리
- 13.2 주의사항
- 13.2.1 파티션의 제약 사항
- 13.2.2 파티션 사용 시 주의사항
- 13.3 MySQL 파티션의 종류
- 13.3.1 레인지 파티션
- 13.3.2 리스트 파티션
- 13.3.3 해시 파티션
- 13.3.4 키 파티션
- 13.3.5 리니어 해시 파티션/리니어 키 파티션
- 13.3.6 파티션 테이블의 쿼리 성능
- 13.1 개요
- ▣ 14장: 스토어드 프로그램
- 14.1 스토어드 프로그램의 장단점
- 14.1.1 스토어드 프로그램의 장점
- 14.1.2 스토어드 프로그램의 단점
- 14.2 스토어드 프로그램의 문법
- 14.2.1 예제 테스트 시 주의사항
- 14.2.2 스토어드 프로시저
- 14.2.3 스토어드 함수
- 14.2.4 트리거
- 14.2.5 이벤트
- 14.2.6 스토어드 프로그램 본문(Body) 작성
- 14.3 스토어드 프로그램의 보안 옵션
- 14.3.1 DEFINER와 SQL SECURITY 옵션
- 14.3.2 DETERMINISTIC과 NOT DETERMINISTIC 옵션
- 14.4 스토어드 프로그램의 참고 및 주의사항
- 14.4.1 한글 처리
- 14.4.2 스토어드 프로그램과 세션 변수
- 14.4.3 스토어드 프로시저와 재귀 호출
- 14.4.4 중첩된 커서 사용
- 14.1 스토어드 프로그램의 장단점
- ▣ 15장: 데이터 타입
- 15.1 문자열(CHAR와 VARCHAR)
- 15.1.1 저장 공간
- 15.1.2 저장 공간과 스키마 변경(Online DDL)
- 15.1.3 문자 집합(캐릭터 셋)
- 15.1.4 콜레이션(Collation)
- 15.1.5 비교 방식
- 15.1.6 문자열 이스케이프 처리
- 15.2 숫자
- 15.2.1 정수
- 15.2.2 부동 소수점
- 15.2.3 DECIMAL
- 15.2.4 정수 타입의 칼럼을 생성할 때의 주의사항
- 15.2.5 자동 증가(AUTO_INCREMENT) 옵션 사용
- 15.3 날짜와 시간
- 15.3.1 자동 업데이트
- 15.4 ENUM과 SET
- 15.4.1 ENUM
- 15.4.2 SET
- 15.5 TEXT와 BLOB
- 15.6 공간 데이터 타입
- 15.6.1 공간 데이터 생성
- 15.6.2 공간 데이터 조회
- 15.7 JSON 타입
- 15.7.1 저장 방식
- 15.7.2 부분 업데이트 성능
- 15.7.3 JSON 타입 콜레이션과 비교
- 15.7.4 JSON 칼럼 선택
- 15.8 가상 칼럼(파생 칼럼)
- 15.1 문자열(CHAR와 VARCHAR)
- ▣ 16장: 복제
- 16.1 개요
- 16.2 복제 아키텍처
- 16.3 복제 타입
- 16.3.1 바이너리 로그 파일 위치 기반 복제
- 16.3.2 글로벌 트랜잭션 아이디(GTID) 기반 복제
- 16.4 복제 데이터 포맷
- 16.4.1 Statement 기반 바이너리 로그 포맷
- 16.4.2 Row 기반 바이너리 로그 포맷
- 16.4.3 Mixed 포맷
- 16.4.4 Row 포맷의 용량 최적화
- 16.5 복제 동기화 방식
- 16.5.1 비동기 복제(Asynchronous replication)
- 16.5.2 반동기 복제(Semi-synchronous replication)
- 16.6 복제 토폴로지
- 16.6.1 싱글 레플리카 복제 구성
- 16.6.2 멀티 레플리카 복제 구성
- 16.6.3 체인 복제 구성
- 16.6.4 듀얼 소스 복제 구성
- 16.6.5 멀티 소스 복제 구성
- 16.7 복제 고급 설정
- 16.7.1 지연된 복제(Delayed Replication)
- 16.7.2 멀티 스레드 복제(Multi-threaded Replication)
- 16.7.3 크래시 세이프 복제(Crash-safe Replication)
- 16.7.4 필터링된 복제(Filtered Replication)
- ▣ 17장: InnoDB 클러스터
- 17.1 InnoDB 클러스터 아키텍처
- 17.2 그룹 복제(Group Replication)
- 17.2.1 그룹 복제 아키텍처
- 17.2.2 그룹 복제 모드
- 17.2.3 그룹 멤버 관리(Group Membership)
- 17.2.4 그룹 복제에서의 트랜잭션 처리
- 17.2.5 그룹 복제의 자동 장애 감지 및 대응
- 17.2.6 그룹 복제의 분산 복구
- 17.2.7 그룹 복제 요구사항
- 17.2.8 그룹 복제 제약 사항
- 17.3 MySQL 셸
- 17.4 MySQL 라우터
- 17.5 InnoDB 클러스터 구축
- 17.5.1 InnoDB 클러스터 요구사항
- 17.5.2 InnoDB 클러스터 생성
- 17.6 InnoDB 클러스터 모니터링
- 17.7 InnoDB 클러스터 작업
- 17.7.1 클러스터 모드 변경
- 17.7.2 프라이머리 변경
- 17.7.3 인스턴스 제거
- 17.7.4 클러스터 해체
- 17.7.5 클러스터 및 인스턴스 설정 변경
- 17.8 InnoDB 클러스터 트러블슈팅
- 17.8.1 클러스터 인스턴스 장애
- 17.8.2 클러스터의 정족수 손실
- 17.9 InnoDB 클러스터 버전 업그레이드
- 17.10 InnoDB 클러스터 제약 사항
- ▣ 18장: Performance 스키마 & Sys 스키마
- 18.1 Performance 스키마란?
- 18.2 Performance 스키마 구성
- 18.2.1 Setup 테이블
- 18.2.2 Instance 테이블
- 18.2.3 Connection 테이블
- 18.2.4 Variable 테이블
- 18.2.5 Event 테이블
- 18.2.6 Summary 테이블
- 18.2.7 Lock 테이블
- 18.2.8 Replication 테이블
- 18.2.9 Clone 테이블
- 18.2.10 기타 테이블
- 18.3 Performance 스키마 설정
- 18.3.1 메모리 사용량 설정
- 18.3.2 데이터 수집 및 저장 설정
- 18.4 Sys 스키마란?
- 18.5 Sys 스키마 사용을 위한 사전 설정
- 18.6 Sys 스키마 구성
- 18.7 Performance 스키마 및 Sys 스키마 활용 예제
- 18.7.1 호스트 접속 이력 확인
- 18.7.2 미사용 DB 계정 확인
- 18.7.3 MySQL 총 메모리 사용량 확인
- 18.7.4 스레드별 메모리 사용량 확인
- 18.7.5 미사용 인덱스 확인
- 18.7.6 중복된 인덱스 확인
- 18.7.7 변경이 없는 테이블 목록 확인
- 18.7.8 I/O 요청이 많은 테이블 목록 확인
- 18.7.9 테이블별 작업량 통계 확인
- 18.7.10 테이블의 Auto-Increment 칼럼 사용량 확인
- 18.7.11 풀 테이블 스캔 쿼리 확인
- 18.7.12 자주 실행되는 쿼리 목록 확인
- 18.7.13 실행 시간이 긴 쿼리 목록 확인
- 18.7.14 정렬 작업을 수행한 쿼리 목록 확인
- 18.7.15 임시 테이블을 생성하는 쿼리 목록 확인
- 18.7.16 트랜잭션이 활성 상태인 커넥션에서 실행한 쿼리 내역 확인
- 18.7.17 쿼리 프로파일링
- 18.7.18 ALTER 작업 진행률 확인
- 18.7.19 메타데이터 락 대기 확인
- 18.7.20 데이터 락 대기 확인
예제 코드
- GitHub 저장소: https://github.com/wikibook/realmysql80
- ZIP 형식으로 다운로드: https://github.com/wikibook/realmysql80/archive/refs/heads/main.zip
정오표
-
4쪽, 2번째 불릿 항목
PIPE_AS_CONCAT
==>
PIPES_AS_CONCAT
-
13쪽, 본문 밑에서 4번째 줄
sql_mode 시스템 변숫값에
PIPE_AS_CONCAT을 설정하면 된다.==>
sql_mode 시스템 변숫값에
PIPES_AS_CONCAT을 설정하면 된다. -
23쪽, 본문 9번째 줄
dept_emp칼럼(4글자×4바이트)과==>
dept_no칼럼(4글자×4바이트)과 -
78쪽, 페이지 중간 예제의 2번째 줄
mysql> SELECT * FROM employees GROUP BY first_name LIMIT 0, 10;==>
mysql> SELECT first_name FROM employees GROUP BY first_name LIMIT 0, 10; -
91쪽, 본문 밑에서 3번째 줄
이때 조인을 수행한 횟수는
12,000번(3000 * 4)정도라는 것을 알 수 있다. 그리고 조인의 결과12,000건의 레코드를 임시 테이블에 저장하고 GROUP BY 처리를 통해3000건으로 줄였다.==>
이때 조인을 수행한 횟수는
30,000번(3,000 * 10)정도라는 것을 알 수 있다. 그리고 조인의 결과30,000건의 레코드를 임시 테이블에 저장하고 GROUP BY 처리를 통해3,000건으로 줄였다. -
116쪽, 페이지 상단 쿼리(4번째 줄 변경)
mysql> WITH cte1 AS (SELECT * FROM departments), cte2 AS (SELECT * FROM dept_emp) SELECT * FROM temp1 INNER JOIN cte2 ON cte2.dept_no=cte1.dept_no;==>
mysql> WITH cte1 AS (SELECT * FROM departments), cte2 AS (SELECT * FROM dept_emp) SELECT * FROM cte1 INNER JOIN cte2 ON cte2.dept_no=cte1.dept_no; -
166쪽, 본문 밑에서 5번째 줄
MySQL 8.0에서는
pt-online-schema-changed와 같은 도구는==>
MySQL 8.0에서는
pt-online-schema-change와 같은 도구는 -
234쪽, 본문 2번째 단락
그렇다면 MySQL 8.0 버전에서 공간 데이터를 저장할 때 SRID를 별도로 지정해서 저장하는 것이 좋을지, 아니면 그냥 예전처럼 SRID를 별도로 지정하지 않는 것이 좋을지 혼란스러울 수 있다. MySQL 서버의 공간 데이터에서 SRID는 문자열 타입의 문자 셋이나 콜레이션과 비슷한 수준으로 비유할 수 있다.
MySQL 서버의 문자열 타입은 별도로 콜레이션(예를 들어, utf8mb4_general_ci)을 지정할 수 있지만 바이너리 콜레이션(utf8mb4_bin)으로 지정할 수도 있다. 바이너리 콜레이션에 비해 utf8mb4_general_ci 콜레이션은 대소문자를 동일시한다거나 하는 추가적인 비교 요건을 더 선택할 수 있다. 공간 데이터의 SRID 또한 별도로 SRID를 지정하면 실제 지구상의 좌표를 관리하는 데 있어 MySQL 서버가 지원하는 기능을 제대로 활용하지 못하게 된다.대표적으로 SRID가 0으로 설정된 데이터에대해거리 계산은 실제 지구 구면체 상의 거리 계산을 하는 것이 아니다. SRID가 0인 공간 데이터는 단위를 가지지 않기 때문이다.==>
그렇다면 MySQL 8.0 버전에서 공간 데이터를 저장할 때 SRID를 별도로 지정해서 저장하는 것이 좋을지, 아니면 그냥 예전처럼 SRID를 별도로 지정하지 않는 것이 좋을지 혼란스러울 수 있다. MySQL 서버의 공간 데이터에서 SRID는 문자열 타입의 문자 셋이나 콜레이션과 비슷한 수준으로 비유할 수 있다.
MySQL 서버의 문자열 타입은 별도로 콜레이션을 지정할 수 있지만, 기본으로 지정되는 콜레이션을 사용할 수도 있다. 그러나 기본으로 지정되는 콜레이션이 원하는 문자열 비교 요건을 만족하지 못할 수 있다. 예를 들어 문자열에 대해 대소문자 구분이 필요한 경우에는 바이너리 콜레이션(utf8mb4_bin)을 사용해야 하며, 추가적인 문자열 비교 요건이 있는 경우 다른 콜레이션을 선택해서 사용해야 한다. 공간 데이터의 SRID 또한 별도로 SRID를 지정할 수 있지만, 만약 지정하지 않고 사용하는 경우 실제 지구상의 좌표를 관리하는 데 있어 MySQL 서버가 지원하는 기능을 제대로 활용하지 못할 수 있다.대표적으로 SRID가 0으로 설정된 데이터에대한거리 계산은 실제 지구 구면체 상의 거리 계산을 하는 것이 아니다. SRID가 0인 공간 데이터는 단위를 가지지 않기 때문이다. -
235쪽, 본문 7번째 줄
하지만 세 번째는
지리 좌표계를 사용하기 때문에 지구 구체 기반이기 때문에거리 값이 완전히 다르게 계산된 것이다.==>
하지만 세 번째는
지구 구체 기반인 지리 좌표계를 사용하고 있기 때문에거리 값이 완전히 다르게 계산된 것이다. -
280쪽, 본문 첫 번째 단락 삭제
레인지 파티션을 사용하는 테이블에서 이렇게 파티션을 삭제할 때 항상 가장 오래된 파티션 순서로만 삭제할 수 있다. 레인지 파티션이 4개가 있는데, 중간에 있는 파티션을 먼저 삭제할 수는 없다. 레인지 파티션을 사용하는 테이블에서는 가장 마지막 파티션만 새로 추가할 수 있고, 가장 오래된 파티션만 삭제할 수 있다.
==>
(삭제) -
429쪽, 밑에서 3번째 줄
이 같은 방법을 스케일
아웃(Scale-up)이라고 하며,==>
이 같은 방법을 스케일
아웃(Scale-out)이라고 하며,