쿼리 튜닝을 진행하며 얻은 팁과 정리를 계속해서 추가할 예정이다. 실행 계획 정리 | Notion 쿼리 튜닝을 진행하며 얻은 팁과 정리를 계속해서 추가할 예정이다. hyunsb.notion.site 참고하면 좋은 글 [SQL튜닝] MySQL 쿼리 튜닝, 쿼리 실행계획, Explain 실행계획을 분석해서 SQL 성능튜닝을 해보자(feat.MySQL)
분류 전체보기
☁️ 클러스터링 인덱스 데이터베이스를 조회할 때, 주로 비슷한 값을 통시에 조회하는 경우가 많다고 한다. 이를 착안하여 비슷한 값(보통 프라이머리 키 기준)으로 묶어서 저장하는 것을 클러스터링 인덱스라고 한다. 클러스터링 인덱스는 다른 세컨더리 인덱스와는 다르게 인덱스의 값으로 레코드의 물리적인 주소를 가지고 있다. 레코드는 클러스터링 키 값에 의해 저장위치가 결정되며, 특정 레코드의 클러스터링 키의 데이터가 변경된다면 해당 레코드의 물리적인 위치까지 변경되는 코스트 높은 작업이 수행될 것이다. 이처럼 InnoDB에서 레코드는 클러스터링 인덱스에 상당히 의존적이기에 프라이머리 키를 신중하게 결정해야 한다. InnoDB에서는 각 테이블에 클러스터링 인덱스가 무조건 생성된다. 클러스터링 인덱스는 키 값으로 ..
☁️ 인덱스 (index) 인덱스는 책의 맨 끝에 있는 찾아보기라고 많이 설명된다. 특정 데이터를 이 찾아보기(인덱스)를 통해 데이터의 주소로 바로 이동할 수 것이다. 인덱스는 인덱스의 칼럼과 해당 레코드가 저장된 주소를 키와 값 쌍으로 찾아보기 쉽게 정렬하여 저장한다. (InnoDB는 레코드 주소가 아닌 PK를 주소처럼 사용) select 문장의 경우 인덱스를 통해 특정 레코드를 검색하는 것이 인덱스 없이 전체 테이블에서 레코드를 검색하는 방식보다 훨씬 빠를 것이다. 하지만 insert, update, delete 문장은 어떨까? 인덱스는 정렬되어 저장된다고 앞서 말했다. 레코드의 변경이 생기는 insert, update, delete 문장에 의해 인덱스와 연관이 있는 레코드에 변경이 생기는 경우 인덱..
☁️ MySQL 엔진의 잠금 MySQL에서 사용되는 잠금은 스토리지 엔진 레벨의 잠금과 MySQL 엔진 레벨의 잠금으로 나눌 수 있다. MySQL 엔진은 스토리지 엔진을 제외한 MySQL 서버의 모든 영역으로 보면되는데, MySQL 엔진 레벨의 잠금은 스토리지 엔진에도 영향을 미치지만, 반대로 스토리지 엔진 레벨의 잠금은 MySQL 엔진에 영향을 미치지 않는다. MySQL 엔진에서 제공하는 락의 종류를 간단하게만 정리하고 넘어가보려 한다. 글로벌 락 (Global Lock) MySQL에서 제공하는 잠금 가운데 가장 범위가 크다. 하나의 세션이 글로벌 락을 획득하면 다른 세션에서의 Select 작업 외의 모든 작업은 글로벌 락의 해제를 기다려야 한다. 이는 MySQL 서버 전체에 대한 락이므로 작업 테이블..
☁️ 트랜잭션 트랜잭션이란 우리가 하나라고 생각하는 작업이다. 예를 들어 나에게 “샤워를 한 뒤 바디로션을 바른다.”는 하나의 작업이다. 엄밀하게 따지면 “샤워를 한다.” 와 “바디로션을 바른다.”로 행동이 나눠지지만 그냥 하나의 작업으로 묶는 것이다. 트랜잭션도 동일하다. “A테이블을 읽고 a레코드가 존재한다면, A테이블의 a레코드를 수정한다.” 라는 두 작업을 하나의 작업으로 인식하게 하는 것이다. 하나의 작업은 반드시 성공(커밋)하거나 하나라도 실패 시 롤백되어야 한다. A테이블을 읽는 작업을 성공하고 a레코드를 수정하는 작업에서 오류가 발생하였다면 롤백되어야 한다. 유의할 점 그런데 여기서 유의해야할 사항이 있다. “과연 A테이블을 읽고 a레코드가 존재한다면, A테이블의 a레코드를 수정한다” 라는..
아래 포스팅과 이어집니다. InnoDB 스토리지 엔진 - 버퍼 풀과 리두, 언두 로그 ☁️ InnoDB 스토리지 엔진 아키텍처 스토리지 엔진은 MySQL 엔진에서 핸들러에 의해 전달된 명령을 수행하는 엔진이다. 데이터를 메모리에 쓰고 읽는 작업을 수행한다. 이 중 MySQL에서 가장 많이 hyunsb.tistory.com ☁️ 어댑티브 해시 인덱스 InnoDB는 내부적으로 자주 사용되는 데이터에 페이지 대해 자동으로 생성되는 인덱스를 가지고 있다. 보통 테이블 인덱스라고 하면 B-Tree 구조로 생성하는데, 어댑티브 해시 인덱스는 이름처럼 해시 값을 가진다. B-Tree 인덱스는 O(logN)의 빠른 탐색 속도를 가지지만, 수천 개의 스레드가 동시에 이를 처리한다면 속도는 느려질 수 밖에 없다. 이러한 ..
☁️ InnoDB 스토리지 엔진 아키텍처 스토리지 엔진은 MySQL 엔진에서 핸들러에 의해 전달된 명령을 수행하는 엔진이다. 데이터를 메모리에 쓰고 읽는 작업을 수행한다. 이 중 MySQL에서 가장 많이 사용되는 엔진은 InnoDB 스토리지 엔진이다. InnoDB 스토리지 엔진은 내부적으로 Buffer pool을 가지고 있어 데이터 캐싱을 지원한다. 또한 쓰기 작업에 대해 지연된 쓰기를 지원하고, 백그라운드 스레드가 주기적으로 더티 페이지를 확인하여 디스크에 데이터를 적재하고 동기화하는 작업을 수행한다. InnoDB 스토리지 엔진은 레코드(튜플) 기반 잠금을 제공한다. 튜플 기반 잠금은 테이블 기반 잠금보다 좁은 범위 락을 사용하고, 각 트랜잭션이 튜플을 기준으로 동작할 수 있기에 높은 동시성 처리가 가..
☁️ 쿼리 실행 구조 사용자가 MySQL에 쿼리를 요청하면 MySQL은 아래의 그림과 같은 절차를 수행한다. 쿼리 파서 사용자의 요청으로 들어온 쿼리 문장을 토큰으로 분리하여 트리 형태의 구조(파서 트리)로 만들어 내는 작업을 수행한다. 이 때, 사용자가 요청한 쿼리의 기본 문법 오류가 발견되고 리턴된다. 전처리기 쿼리 파서 과정에서 만들어진 파서 트리를 기반으로 쿼리 문장에 문제점이 있는지 확인한다. 테이블 이름이나 컬럼, 내장 함수 같은 구문에 오류가 있는지 확인하고, 실제로 존재하는 테이블인지 권한상 접근 불가능한 테이블인지 판단 후 오류 검출 시 리턴한다. 옵티마이저 옵티마이저는 MySQL 엔진의 뇌와 같은 존재이다. 쿼리 문장을 더 저렴한 비용으로 빠르게 처리할 수 있는지를 판단하여 실행 계획을..
☁️ MySQL 사용이유 Oracle과 비교한 MySQL의 경쟁력은 가격이다. 방대한 양을 저장하고 트래픽을 수용하기에 Oracle RDBMS는 너무 비싸다. MySQL은 Oracle 만큼이나 레퍼런스가 많고 안정적이기에 사용하기에 좋다고 생각한다. ☁️ MySQL 아키텍처 MySQL은 크게 MySQL 엔진과 스토리지 엔진으로 구분할 수 있다. MySQL엔진: 쿼리 파싱, 옵티마이저 등 사용자 요청에 대한 전반적인 처리를 담당한다. 스토리지 엔진: 디스크에 쓰기, 읽기 작업을 수행한다. 스토리지 엔진 마다 수행 방식이 상이하다. MySQL엔진 MySQL 엔진은 클라이언트로부터의 접속 및 쿼리 요청을 처리하는 커넥션 핸들러, SQL파서, 전처리기, 쿼리를 최적화 해주는 옵티마이저가 중심을 이룬다. 스토리지..