2.1 물리 엔진과 오브젝트 용어

2.1.1 DB 엔진 용어

전체적인 구조

푸드코트에서 음식을 주문하는 과정과 마찬가지로, 사용자는 DB에서 원하는 데이터를 가져오고자 SQL 문을 실행한다.

실행된 SQL 문은 MySQL 엔진에서 문법 에러가 있는지, DB에 존재하는 테이블 대상으로 SQL 문을 작성했는지와 같은 세부 사항을 다양한 문법 및 구문으로 검사한다(파싱 작업을 하는 파서 역할).

이후 사용자가 요청한 데이터를 빠르고 효율적으로 찾아가는 전략적 계획을 수립한다(옵티마이저 역할).

이 계획을 토대로 스토리지 엔진에 위치한 데이터까지 찾아간 뒤 해당 데이터를 MySQL 엔진으로 전달한다.

MySQL 엔진은 전달된 데이터에서 불필요한 부분을 필터링(제거, 변경) 후 필요한 연산 수행 뒤 사용자에게 최종 결과를 알려준다.

스토리지 엔진

(InnoDB, MyISAM, Memory 등) 스토리지 엔진은 SQL 문 토대로 DB에 저장된 디스크나 메모리에서 필요한 데이터를 가져오는 역할을 수행한다. 추출한 데이터를 MySQL 엔진으로 보내주는 역할.

일반적으로 온라인상의 트랜잭션 발생으로 데이터를 처리하는 OLTP(online transaction processing)환경이 대다수인 만큼 주로 InnoDB 를 쓴다. 그 밖에도 대량의 쓰기 트랜잭션이 발생하면 MyISAM을, 메모리 데이터를 로드하여 빠르게 읽는 효과를 내려면 Memory 엔진을 쓰는식으로 응용하여 스토리지 엔진을 선택할 수 있다.

MySQL, MariaDB에서 기본 제공하는 스토리지 엔진 종류는 상이하다. 여기서 눈여겨볼 엔진은 MariaDB의 Sequence 엔진으로, 오라클의 시퀀스 오브텍트와 유사하게 동작하며 MySQL과 MariaDB가 뿌리는 같지만 제공하는 엔진 목록이 일치하지 않는다는 점을 확인할 수 있다.

MySQL 엔진

MySQL 엔진은 사용자가 요청한 SQL 문을 넘겨받은 뒤 SQL 문법 검사와 적절한 오브텍트 활용 검사를 하고, SQL 문을 최소 단위로 분리해 원하는 데이터를 빠르게 찾는 경로를 모색하는 역할을 한다. 이후 스토리지 엔진으로 부터 전달받은 데이터 대상으로 불필요한 데이터는 제고, 가공, 연산하는 역할.

즉, SQL문의 시작 및 마무리 단계에서 MySQL 엔진이 관여하며, 스토리지 엔진으로부터 필요한 데이터만을 가져오는 핵심 역할을 담당한다.

  • 사용자가 요청한 쿼리문 넘겨 받고서 문법 검사, 적절한 오브젝트 활용검사 후, 쿼리 문을 최소 단위로 분리해 원하는 데이터 빨리 찾는 경로 모색 역할 수행
  • 이후 스토리지 엔진으로 부터 데이터 받고 이 데이터 대상으로 불필요한 데이터 제거, 가공 및 연산
  • 즉, 쿼리의 시작 과 끝을 담당
  • 스토리지 엔진으로 부터 필요한 데이터를 가져오는 핵심 역할 담당

2.1.2 SQL 프로세스 용어

사용자가 SQL 문 수행하면, 파서는 MySQL이 이해할 수 있는 최소 단위로 구성요소를 분리하고 해당 구성요소를 트리로 만든다. 트리를 만드는 과정에서 문법 오류가 있는지 검토한다. 트리의 최소 단위는 <, >, = 등의 기호나 SQL 기호로 분리한다. 만약 트리에 허용되지 않는 문법이 포함된다면 에러 발생과 동시에 실행이 종료된다.

이후 전처리기는 생성된 트리 결과를 토대로, 이미 만들어진 테이블이나 뷰 등으로 구성되지 않았는지, 존재하지 않는 열을 포함하지 않았는지, 조회 권한이 없는 테이블을 조회 하는 지 등 유효성을 검증한다. 만약 유효하지 않은 오브젝트가 있거나 권한이 없는 오브젝트를 호출하면 바로 에러를 발생하여 사용자에게 표시한다.

다음으로 옵티마이저는 트리를 구성하는 오브젝트의 데이터를 효율적으로 가져오기 위해 시간은 적게 소요되면서 비용 효율적인 경로로 데이터를 검색하는 방법에 관한 실행 계획을 수립한다. 엔진 실행기는 이전에 수립된 실행 계획으로 스토리지 엔진을 호출해 필요한 데이터를 가져온다. 이후 엔진 실행기는 스토리지 엔진을 통해서 가져온 데이터 중 불필요한 데이터를 필터링하여 사용자가 원하는 결과를 전달한다. 이렇게 SQL 실행 과정에서 핵심 역할을 수행하는 오브젝트는 크게 파서, 전처리기, 옵티마이저, 엔진 실행기로 구분된다.

파서

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

전처리기

preprosessor는 MySQL 엔진에 해당하는 오브젝트. 파서가 생성한 트리 기반으로 SQL 문에 구조적 문제 없는지 파악. SQL 문에 작성된 테이블, 열, 함수, 뷰와 같은 오브젝트가 실질적으로 이미 생성된 오브젝트인지, 접근 권한은 부여되어 있는지 확인하는 역할.

옵티마이저

optimizer 는 MySQL 의 핵심 엔진 중 하나. DBMS에서 두뇌라고 불러도 과언이 아닌 핵심적인 역할. 전달된 파서 트리를 토대로 필요하지 않은 조건은 제거 또는 연산 과정을 단순화 한다. 나아가 어떤 순서로 테이블에 접근할지, 인덱스를 사용할지, 어떤 인덱스를 사용할지, 정렬할 때 인덱스를 사용할지 아니면 임시 테이블을 사용할지와 같은 실행 계획을 수립한다.

단, 실행 계획으로 도출할 수 있는 경우의 수가 지나치게 많으면 실행 계획을 수립하고 비용을 산정하여 최적의 실행 계획을 택하기까지 너무 오래 결리는 만큼 모든 실행 계획을 판단하지는 않음. 이는 옵티마이저가 선택한 실행 계획이 최상의 실행 계획이 아닐 가능성도 있다는걸 의미한다.

실행 계획을 수립하는 작업 자체만으로로 사용자의 대기 시간과 하드웨어 리소스를 점유하므로, 시간과 리소스에 제한을 두고 실행 계획을 선정해야한다.

이처럼 옵티마이저가 예측한 실행 계획이 항상 최적은 아닌 만큼 개발자의 손길이 필요할 수 있다.

엔진 실행기

engine executor 는 MySQL 엔진과 스토리지 엔진 영역 모두 걸치는 오브젝트. 옵티마이저에서 수립한 실행 계획을 참고하여 스토리지 엔진에서 데이터를 가져온다. 이후 MySQL 엔진에서는 읽어온 데이터를 정렬하거나 조인하고, 불필요한 데이터는 필터링 처리하는 추가 작업을 한다. 따라서 MySQL 엔진의 부하를 줄이려면 스토리지 엔진에서 가져오는 데이터양을 줄이는게 매우 중요하다.

2.1.3 DB 오브젝트 용어

DB의 오브젝트란 다음과 같은걸 지칭한다. 행, 열, 테이블, 기본 키, 외래 키(외부 테이블 항상 참조하면서 외부 테이블의 데이터가 변경되면 함께 영향을 받는 관계를 설정하는 키, 정합성 향상)

  • 가상의 테이블
  • 제약적으로 볼 수 있는 것
  • 특정 속성만 보여주는 환경 조성이 가능해서 보안성 측면에서 가치 있다
  • 사용 이유
    • 일부 데이터에 대해서만 데이터 공개
    • 노출 민감 데이터는 노출 제약
    • 여러개 테이블 조인시 성능 고려한 최적화된 뷰를 생성함으로써 일관된 성능 제공 가능(뭔소릴까)

2.2 논리적인 SQL 개념 용어

2.2.1 서브쿼리 위치에 따른 SQL 용어

  • 쿼리 안의 보조쿼리
  • 가장 바깥의 SELECT 문인 메인쿼리 기준으로 내부에 SELECT 문 추가로 작성하여 서브쿼리 만듬
  • 위치에 따라

2.2.2 메인쿼리와의 관계성에 따른 SQL 용어

2.2.4 조인 연산방식 용어

내부 조인

  • 교집합 방식
  • 양쪽에 모두 존재하는 데이터만 반환
-- 명시적 조인
SELECT 학생.학번, 학생.이름, 지도교수.교수명
  FROM 학생
  JOIN 지도교수
    ON 학생.학번 = 지도교수.학번
-- 암시적 조인
SELECT 학생.학번, 학생.이름, 지도교수.교수명
  FROM 학생, 지도교수
 WHERE 학생.학번 = 지도교수.학번
 

외부 조인

  • 왼쪽 외부 조인과 오른쪽 외부 조인
    • 조인 조건이 일치하지 않더라도 기준 테이블의 결과는 최종 결과에 포함 시킨다.
SELECT 학생.학번, 학생.이름, 지도교수.교수명
  FROM 학생
  LEFT OUTER JOIN 지도교수
			   ON 학생.학번 = 지도교수.학번

전체 외부 조인 이라는게 있는데 좌측, 우측 외부조인 통합된 방식 MySQL, MariaDB 에서는 미지원

교차 조인

  • 데카르트 곱(cartesian product)
  • 조인에 참여하는 테이블에서 발생 가능한 모든 조합 찾아내여 반환
  • 연산과정에서
    • 시간적
    • 공간적
    • 리소스 점유의 오버헤드 발생
SELECT 학생.학번, 학생.이름, 지도교수.학번, 지도교수.교수명
  FROM 학생
CROSS JOIN 지도교수
-- 암시적 교차 조인 
-- WHRER 의 조인 조건문이나 JOIN 키워드 명시 않으면 교차 조인이 수행
SELECT 학생.학번, 학생.이름, 지도교수.학번, 지도교수.교수명
  FROM 학생

자연 조인

  • 2개의 테이블에 동일한 열명이 있을때 조인 조건절(ON)을 따로 작성 않아도 자동으로 조인 수행
  • 조인이 제대로 성사되면 내부 조인과 동일한 결과 출력
  • 이때, 조인하는 열들의 데이터 유형이 서로 달라도 자연 조인이 수행됨
-- 명시적
-- 여기서 ON 을 입력하면 에러발생
SELECT 학생.*, 지도교수.* 
  FROM 학생
NATURAL JOIN 지도교수

만약 두 테이블간 공통으로 존재하는 열명이 하나도 없다면?

SELECT 학생.*, 지도교수.* 
  FROM 학생
NATURAL JOIN 지도교수
  • 결과는…! 교차 조인이 수행된다! 즉, 자연 조인은 동일한 열명이 있을 때는 내부 조인 그렇지 않으면 교차 조인. 자연 조인은 열명 변경에 따라 출력 결과 달라져서 의도치 않은 결과 가능성 존재.

실무에서는 대부분 조인 방식과 조건 명시하는 내부 조인이나 외부 조인 활용

2.2.5 조인 알고리즘 용어

드라이빙 테이블과 드리븐 테이블

먼저 접근되는 테이블이 드라이빌 테이블, 뒤늦게 접근되는 테이블을 드리븐 테이블이라 한다.

  • 드라이빙 테이블에서 많은 건수 반환되면 이 결과 가지고 드리븐 테이블에 접근하게 된다.
  • 즉, 성능을 고려하면 가능하면 적은 결과가 반환될 것으로 예상되는 드라이블 테이블을 선정하고 조인 조건절의 열이 인덱스로 설정되도록 구성해야 함

중첩 루프 조인

  • nested loop join(NL Join)
  • 드라이빙 테이블 데이터 1건당 드리븐 테이블을 반복해 검색

기본 키, 인덱스 없는 경우

SELECT 학생.학번,학생.이름, 비상연락망.관계, 비상연락 망
FROM 학생
JOIN 비상연락망
ON 학생.학번 = 비상연락망.학번
WHERE 학생•학번 IN ( 1 , 100 )

학번 1, 100에 해당하는 학생 정보와 그에 조인되는 비상연락망 정보를 가져오려함. 먼저 여긴 기본 키, 인덱스가 없어서 (100 + 1000), (100 + 1000) 이렇게 2200건의 데이터를 조회한다. 학번으로 인덱싱 (1+2) + (1 + 1) 총 5건 데이터 조회

블록 중첩 루프 조인

배치 키 액세스 조인

해시 조인

  • 한 테이블(보통은 더 작은 테이블)의 행 사용해 해시 테이블 만든 후, 다른 테이블 순회하며 해시 테이블 사용하여 조인

  • 하나의 테이블이 서버 메모리에 온전히 들어간다면, 중첩 루프 조인보다 효율적

  • 다만, 메모리가 부족할 경우 성능 저하될 수 있음

  • 동등(=) 조인에서만 사용 가능 작동 방식

  • 빌드 단계

    • 바이트가 더 작은 테이블로 부터 해시 테이블 생성
    • 각 행의 조인 키에 해시 함수 적용해 해시 테이블에 저장
  • 프로브(probe) 단계

    • 다른 테이블 각 행에 대한 조인 키를 해싱하여 앞서 만든 해시값과 비교해 해시 테이블에서 매칭되는 행 찾으면 해당 행들을 조인 결과 테이블에 추가
  • O(M + N)

    • M은 빌드 단계 테이블 행 수
    • N은 프로브 단계 테이블 행 수
  • 성능

    • 큰 데이터 셋에 매우 효율적
    • 특히, 두 테이블 사이에 큰 크기 차이가 있을 때 효율적
    • 등가 조인에서만 사용 가능!

2.3 개념적인 튜닝 용어

2.3.1 기초 용어

오브젝트 스캔 유형

오브텍트 스캔 유형은 테이블 스캔과 인덱스 스캔으로 나뉜다. 테이블 스캔은 인덱스 거치지 않고 디스크에 위치한 테이블에 접근하는 유형. 인덱스 스캔은 인덱스로 테이블 데이터를 찾아가는 유형.

테이블 풀 스캔

  • 바로 테이블로 직행하여 처음부터 끝까지 데이터 훓는 방식
  • WHERE 조건문 기준으로 활용할 인덱스 없거나, 전체 데이터 대비 대량의 데이터가 필요할 때 수행 할 수 있음
  • 인덱스 없이 사용하는 유일한 스캔 방식

인덱스 범위 스캔

  • 말 그대로 인덱스를 범위 기준으로 스캔
  • BETWEEN ~ AND
  • <, >, LIKE 등 비교 연산 및 구분에 포함 될 경우 수행
  • 좁은 범위 스캔의 경우는 성능적으로 매우 효율적

인덱스 풀 스캔

  • 말 그대로 인덱스 처음부터 끝까지 수행
  • 단, 테이블에 접근 않고 인덱스로 구성된 열 정보만 요구하는 SQL 문에서 인덱스 풀 스캔이 수행
  • 인덱스는 테이블보다 상대적으로 양이 적어 테이블 풀 스캔보다 성능상 유리

인덱스 고유 스캔

  • index unique scan 은 기본 키나 고유 인덱스로 테이블에 접근
  • 인덱스 사용하는 스캔 방식 중 가장 효율적
  • WHERE 절에 = 조건으로 작성
  • 해당 조인 열이 기본 키 또는 고유 인덱스 선두 열로 설정되었을때 활용

인덱스 루스 스캔

  • indes loose scan 은 인덱스의 필요한 부분만 골라 스캔
  • 인덱스 범위 스캔처럼 넓은 범위 전부 접근 X
  • WHERE 기준 필요한 데이터와 필요하지 않은 데이터 구분한 뒤 불필요한 인덱스 키 무시
  • 보통 GROUP BY, MAX(), MIN() 함수가 포함되면 작동
  • 이미 오름차순 정렬된 인덱스에서 최대값이나 최솟값 필요한 경우 이에 해당

인덱스 병합 스캔

  • index merge scan은 테이블 내에 생성된 인덱스들 통합해서 스캔
  • WHERE 문 조건절의 열들이 서로 다른 인덱스로 존재하면 옵티마이저가 해당하는 인덱스를 가져와 모두 활용하는 방식
  • 통합 방법
    • 결합(UNION)
    • 교차(INTERSECTION)
    • 이들 방식은 모두 실행 계획으로 출력됨
  • 이 방식은 물리적으로 따로 존재하는 개별 인덱스 각각 수행
    • 인덱스 접근 시간 몇 배 로 걸림
    • 따라서
      • 별개 생성된 인덱스들은 보통 하나의 인덱스로 통합해 SQL 튜닝 수행
      • SQL 문 자체를 독립된 하나의 인덱스만 수행하도록 변경

디스크 접근 방식

MySQL은 원하는 데이터 얻으려 데이터가 저장된 스토리지의 페이지에 접근한다. 여기서 페이지란 데이터를 검색하는 최소 단위. 페이지 단위로 데이터 읽고 쓰기 가능.

서로 연결된 페이지 차례대로 읽을 수 있고, 여기저기 원하는 페이지를 임의로 열어볼 수도 잇다.

전자를 시퀀셜 액세스, 후자를 랜덤 액세스

시퀀셜 액세스

  • sequential access 는 물리적으로 인접한 페이지를 차례로 읽는 순차 접근 방식
  • 테이블 풀 스캔에서 활용
  • 데이터 찾고자 이동하는 디스크 헤더의 움직임 최소화 작업 시간, 리소스 점유 비용 줄임
  • 테이블 풀 스캔일 때 인접한 페이지를 여러 개 읽는 다중 페이지 읽기(multi page read) 방식 수행

랜덤 액세스

  • 물리적으로 떨어진 페이지에 임의로 접근하는 임의 접근 방식
  • 페이지가 위치한 물리적 위치 고려 X
  • 디스크 헤더가 정해진 순서 모르고 혹은 없이 이동하는 만큼 물리적 움직임 소모, 다중 페이지 읽기 불가,
    • 데이터 접근 수행 시간 오래 걸림
  • 최소한의 페이지에 접근 하도록 접근 범위 줄이고 효율적 인덱스 활용하도록 튜닝 요구됨

조건 유형

SQL 문의 WHERE 절 조건문 기준으로 데이터가 저장된 디스크에 접근하게된다. 맨 처음 데이터를 검색하는 조건을 액세스 조건이라 하고, 디스크에서 가져온 데이터에서 추가로 추출하거나 가공 및 연산하는 조건을 필터 조건이라 한다.

액세스 조건

access condition

  • 디스크에 있는 데이터에 어떻게 접근할것인지 다루는 것
  • SQL 튜닝에서 가장 중요한 핵심 사항
  • 옵티마이저는 WHRER 의 특정 조건문 이용해 소량 데이터 가져오고, 인덱스 통해 시간 낭비 줄이는 조건절 택하여, 스토리지 엔진의 데이터에 접근하고 MySQL 엔진으로 데이터 가져옴

필터 조건

  • 액세스 조건을 이용해 MySQL 엔진으로 가져온 데이터 기준으로, 추가로 불필요한 데이터를 제거하거나 가공하는 조건
  • 예를 들어 AND 에서 엑세스 조건 아니던 조건을 활용해서 필터링 하는것
  • 만약 필터 조건 따라 필터링할 데이터 없다면 매우 훌륭한 SQL 문
  • 필터링 데이터 많으면 왜 비효율적?
    • 스토리지 엔진에서 MySQL 엔진으로 데이터 전달하는 오버헤드
    • 필터 조건으로 제거 될 데이터면 스토리지 엔진의 데이터에 접근 과정에서 같이 제외되는게 성능적으로 효율적
  • 필터 조건으로 제거되는 데이터 비율확인하고 특정 SQL 문의 튜닝이 필요한지 판단 가능.
    • 이 비율은 실행 계획의 filtered에서 확인 가능

2.3.2 응용 용어

선택도

  • selectivity
  • 테이블 특정 열 기준 해당 열의 조건절에 따라 선택되는 데이터 비율
    • 해당 열에 중복 데이터 많다면 ‘선택도가 높다’
    • 실제로 조건절에 따라 대량의 데이터가 선택될 것
  • 낮은 선택도가 대용량 데이터에서 원하는 데이터만 골라 내는 능력
  • 낮은 선택도를 가지는 열은 SQL에서 원하는 데이터 빨리 찾기 위한 인덱스 열 생성 시 주요 고려 대상
  • 선택도 = 선택(통과) 데이터 수 / 전체 데이터 수
    • 그러나 선택 데이터 건수 매번 계산할 수 없다
    • 삭제, 수정, 삽입 수시로 발생함
    • 그래서 보통 중복이 제거된 데이터 건수를 활용해 선택도 일반화
  • 변형된 선택도 = 1 / DISTINCT(COUNT 열명)
  • 예제보니 변형된 선택도랑 그냥 선택도 결과가 똑같이나오네 근데 원리는 몰겟;
  • 전체 데이터중 필터를 통과하는 데이터의 비율

카디널리티

https://itholic.github.io/database-cardinality/

  • cardinality
  • 하나의 데이터 유형으로 정의되는 데이터 행의 개수
  • DB에서는 전체 데이터에 접근한 뒤 출력될 것이라 예상되는 데이터 건수
  • 전체 행에 대한 특정 열의 중복 수치 지표
  • 카디널리티 = 전체 데이터 건수 * 선택도
  • 음… 근데 MySQL은 또 다르다함…
    • 중복을 제외한 유일한 데이터 값의 수로 계산
    • 따라서, 특정 열에 중복 값 많으면 카디널리티 낮다
    • 해당 열 조회시 상당수 데이터 거르지 못한체 대량의 데이터 출력 예측이 됨

  • 중복이 크다

    • 카디널리티 작다
  • 중복이 작다

    • 카디널리티 크다
  • 일상 예

    • 주민등록번호
      • 카디널리티 높다
    • 이름
      • 카디널리티 중간
    • 성별
      • 카디널리티 낮다
  • 중복도 낮음, 카디널리티 높음, DISTINCT 결과가 기존에 비해 크지 않다(중복이 적었다)

  • 카디널리티 높고, 선택도 낮은거에 인덱스 걸면 효과가 좋을 가능성이 있음

  • 틀별한 값의 종류

  • 테이블의 행 수에 상대적인 테이블 열의 고유 수

  • 값의 중복이 적으면 카디널리티가 높다. 고유한 것이 많으니

  • 카디널리티가 높은 컬럼에 인덱스를 거는게 유리함

  • 그렇다고 무조건 카디널리티 높은걸 인덱스 걸 필요 없음. 실제 활용도가 적다면 인덱스를 걸어도 활용되지 못하기 때문

  • 어떤게 많이 사용되는지 파악이 필수

힌트

  • 데이터베이스에 힌트를 전달함으로써 의도대로 동작하다록 도울 수 있다
  • MySQL에서의 사용법 예
    • 주석 처럼
      • /*! USE INDEX (ANY_INDEX) */
    • 주석 없이
      • USE INDEX (ANY_INDEX)
    • FROM 절 마지막에 붙임 MySQL, MariaDB 주요 힌트 목록
힌트설명활용도
STRAIGHT_JOINFROM 절에 작성된 테이블 순으로 조인 유도높음
USE INDEX특정 인덱스 사용 유도높음
FORCE INDEX특정 인덱스 사용 강하게 유도낮음
IGNORE INDEX특정 인덱스 못쓰게 유도중간

명시적인 힌트 있어도 옵티마이저 판단하에 비효율적이면 무시당함

힌트 했는데 이후 데이터 변화가 생겨 힌트로 쓴 인덱스가 없어지거나 하면 MySQL, MariaDB는 오류 발생. Oracle은 힌트 무시하고 걍 실행함

콜레이션

collation은 특정 문자셋으로 디비에 저장된 값을 비교하거나 정렬하는 작업의 규칙 의미한다.

통계정보

  • 옵티마이저는 통계정보를 바탕으로 실행 계획 수립
  • 보통 DBA가 관리하는거지만 쿼리 수행자(개발자)도 통계정보가 최신으로 관리되는지, 오래된 통계때문에 쿼리가 엉뚱하게 수행되지 않는지 확인 가능

히스토그램

  • 테이블의 열값이 어떻게 분포되어 있는지 확인하는 통계정보
  • 옵티마이저가 실행 계획 최적화 하고자 참고하는 자료
  • 만약 특정 열값들의 통계정보가 히스토그램으로 수집되잊 않았다면,
    • 중복이 제거된 열갑의 개수 COUNT (DISTINCT 열명))으로 대략적 열값의 분포 예측하고 실행 계획을 수립
  • MySQL에서는 내부적으로 열 분포를 저장할때는 높이균형 히스토그램 방식
    • 저장된 데이터가 수만개 이상이니 이 데이터 그룹화하고, 정해진 버킷만큼 분리해서 열의 통계정보를 저장

Col2 열 대상으로 히스토그램이 어떤 방식으로 저장되는지 보여주는 예시. A ~ ZZZ까지 총 78데이터와 10개의 버킷 있다. 데이터를 버킷에 유사한 건수만큼 나누어 정렬. 그런데 실제 디비에서 관리하는 히스토그램의 버킷은 최대값을 보관.

  1. WHERE에 Col2 = ‘A’ 면 버킷 1에만 접근해서 데이터 분포 파악
  2. Col2 BETWEEN E AND O 면 버킷 2~ 6까지 접근해야됨. 전체 50% 이상 스캔해야되서 인덱스 스캔보다 테이블 풀 스캔으로 쿼리가 수행되도록 통계정보를 제공

https://www.youtube.com/watch?v=juGolQrcreY