[Real MySQL8.0 스터디 week3] 8.5 8.6 8.7 8.8 8.9 8.10 9.1장

Coen·2023년 1월 29일
1

Real MySQL Study

목록 보기
5/5
post-thumbnail

이 글은 Real MySQL 스터디에서 제가 발표한 발표자료입니다.






8.5 전문 검색 인덱스

지금까지 살펴본 인덱스 알고리즘은 일반적으로 크지 않은 데이터 또는 이미 키워드화한 작은 값에 대한 인덱싱 알고리즘이었다.

전문(Full Text) 검색

  • 문서의 내용 전체를 인덱스화하여 특정 키워드가 포함된 문서를 검색하는 것
  • 문서 전체에 대한 분석과 검색을 위한 이러한 인덱싱 알고리즘을 전문 검색 인덱스 라고 한다.
  • InnoDBMyISAM 스토리지 엔진에서 제공하는 일반적인 용도의 B-Tree 인덱스를 사용할 수 없다.

이 책에서는 InnoDB 스토리지 엔진 중심으로 소개하고 있습니다.

8.5.1 인덱스 알고리즘

전문검색에서는 문서 본문의 내용에서 사용자가 검색하게 될 키워드를 분석해 내고, 빠른 검색용으로 사용할 수 있게 이러한 키워드로 인덱스를 구축한다.

문서의 키워드를 인덱싱하는 기법에 따라 크게 두가지로 구분한다.

  1. 단어의 어근 분석 알고리즘
  2. n-gram 분석 알고리즘

8.5.1.1 어근 분석 알고리즘

MySQL서버의 전문 검색 인덱스는 다음과 같은 두 가지 중요한 과정을 거쳐 색인 작업을 수행한다.

  • 불용어(Stop Word) 처리
    • 검색에서 별 가치가 없는 단어를 모두 필터링해서 제거하는 작업
    • 불용어의 개수가 많지 않기 때문에 모두 상수로 정의해서 사용하는 경우가 많다.
    • 불용어 자체를 데이터베이스화해서 사용자가 추가, 삭제 할 수 있게 구현하는 경우도 있다.
  • 어근 분석(Stemming)
    • 검색어로 선정된 단어의 뿌리인 원형을 찾는 작업
    • 오픈소스 형태소 분석 라이브러리인 MeCab 을 플러그인 형태로 지원한다.
    • 한글이나 일본어의 경우 어근 분석보다는 문장의 형태소를 분석해서 명사와 조사를 구분하는 기능이 더 중요하다.
    • 서구권 언어를 위한 형태소 분석기는 MongoDB에서 사용되는 Snowball 이라는 오픈소스가 있다.
    • MeCab 이 제대로 작동하기 위해서는 (1) 단어 사전이 필요하며 (2) 문장을 해체해서 각 단어의 품사를 식별할 수 있는 문장의 구조 인식이 필요하다.
    • MeCab 을 MySQL에 적용하는건 어렵지 않지만 한글에 맞게 완성도를 갖추는 작업은 많은 시간과 노력이 필요하다.

8.5.1.2 n-gram 알고리즘

전문적인 검색 엔진을 고려하는 것이 아니라면 MeCab 을 범용적으로 적용하기 쉽지 않다. 이러한 단점을 보완하기 위한 방법으로 도입된 것이 n-gram 알고리즘이다.

n-gram 이란 본문을 무조건 몇 글자씩 잘라서 인덱싱 하는 방법이다.

형태소 분석에 비해 알고리즘이 단순하고 국가별 언어에 대한 이해와 준비 작업이 필요 없지만, 만들어진 인덱스의 크기는 상당히 큰 편이다.

n-gram의 n은 인덱싱할 키워드의 최소 글자 수를 의미하는데, 일반적으로 2글자로 쪼개는 2-gram 방식이 많이 사용된다.

To be or not to be. That is the question

각 단어는 다음과 같이 띄어쓰기와 마침표를 기준으로 10개의 단어로 구분되고, 2글자씩 충첩해서 토큰으로 분리된다.

각 글자는 중첩해서 2글자씩 토큰으로 구분되고, 구분된 각 토큰을 인덱스에 저장하기만 하면 된다. 이때 중복된 토큰은 하나의 인덱스 엔트리로 병합되어 저장된다.

이렇게 생성된 토큰들에 대해 불용어를 걸러내는 작업을 수행하는데, 불용어와 동일하거나 불용어를 포함하는 경우 걸러서 버린다.

MySQL 내장 불용어는 information_schema.innodb_ft_default_stopword 테이블에서 확인할 수 있다.

8.5.1.3 불용어 변경 및 삭제

앞서 살펴본 불용어 처리는 사용자에게 도움이 되기보다 사용자를 더 혼란스럽게 하는 기능이 될 수 있다. 그래서 불용어 자체를 완전히 무시하거나 사용자가 직접 불용어를 등록하는 방법이 있다.

전문 검색 인덱스의 불용어 처리 무시

불용어 처리를 무시하는 방법은 두 가지가 있다.

  1. 스토리지 엔진에 관계 없이 모든 전문 검색 인덱스에 대해 불용어를 완전히 제거하는 것.

    • my.cnfft_stopword_file 시스템 변수에 빈 문자열을 설정하면 된다.
    ft_stopword_file=''
    • 설정을 변경하면 서버를 재시작해야 변경사항이 변경된다.
  2. InnoDB 스토리지 엔진의 경우 테이블의 전문 검색 인덱스에 대해서만 불용어 처리를 무시할 수도 있다.

    • innodb_ft_enable_stopword 시스템 변수를 OFF 로 설정하면 된다.
    • 다른 스토리지 엔진을 사용하는 테이블은 여전히 내장 불용내장 불용어 처리를 사용한다.
    • 상기 시스템 변수는 동적인 시스템 변수이므로 변경 즉시 적용된다.
    mysql> SET GLOBAL innodb_ft_enable_stopword=OFF;

사용자 정의 불용어 사용

  1. 불용어 목록을 파일로 저장하고 ft_stopword_file 설정에 등록

    ft_stopword_file='/data/my_custom_stopword.txt'
  2. InnoDB 스토리지 엔진 전용으로, 불용어의 목록을 테이블로 저장하는 방식이다.

    1. 불용어 테이블 생성
    2. innodb_ft_server_stopword_table 시스템 변수에 불용어 테이블 설정
    • 불용어 목록을 변경한 이후 전문 검색 인덱스가 생성돼야만 변경된 불용어가 적용된다는 점에 주의하자!
    • innodb_ft_user_stopword_table 시스템 변수를 이용하는 방법도 있는데, innodb_ft_server_stopword_table 와 사용법은 동일하다.
    • 여러 전문 검색 인덱스가 서로 다른 불용어를 사용해야 하는 경우라면 innodb_ft_user_stopword_table 시스템 변수를 이용하면 된다.

8.5.2 전문 검색 인덱스의 가용성

전문 검색 인덱스를 사용하려면 반드시 두 가지 조건을 갖춰야 한다.

  • 쿼리 문장이 전문 검색을 위한 문법( MATCH() AGAINST() )을 사용
  • 테이블이 전문 검색 대상 칼럼에 대해서 전문 인덱스 보유

테이블에 전문 검색 인덱스를 생성했다고 가정하고, 다음의 쿼리로도 원하는 검색 결과를 얻을 수 있다.

mysql> SELECT * FROM tb_test WHERE doc_body LIKE '%애플%';
-- 하지만 풀 테이블 스캔으로 쿼리를 처리한다.

전문 검색 인덱스를 사용하려면 반드시 다음 예제와 같이 MATCH() AGAINST() 구문으로 검색 쿼리를 작성해야 하며, 전문 검색 인덱스를 구성하는 칼럼들은 MATCH 절의 괄호 안에 모두 명시돼야 한다.

mysql> SELECT * FROM tb_test
WHERE MATCH(doc_body) AGAINST('애플' IN BOOLEAN MODE);

8.6 함수 기반 인덱스

일반적인 인덱스는 칼럼 값 일부(칼럼의 값 앞부분) 또는 전체에 대해서만 인덱스 생성이 허용된다.

칼럼의 값을 변형해서 만들어진 값에 대해 인덱스를 구축하는 경우도 있는데, 함수 기반의 인덱스를 활용하면 된다.

함수 기반 인덱스를 구현하는 방법은 다음의 두 가지 이다.

  1. 가상 칼럼을 이용한 인덱스
  2. 함수를 이용한 인덱스

MySQL 서버의 함수 기반 인덱스는 인덱싱할 값을 계산하는 과정의 차이만 존재할 뿐, 실제 인덱스의 내부적인 구조 및 유지관리 방법은 B-Tree 인덱스와 동일하다.

8.6.1 가상 칼럼을 이용한 인덱스

mysql> CREATE TABLE user (
					user_id BIGINT,
					first_name VARCHAR(10),
					last_name VARCHAR(10),
					PRIMARY KEY (user_id)
				);

first_name과 last_name을 합쳐서 검색해야 하는 요건이 생겼다면 가상 칼럼을 추가하고 그 가상 칼럼에 인덱스를 생성할 수 있다.

mysql> ALTER TABLE user
				ADD full_name VARCHAR(30) AS (CONCAT(first_name, ' ', last_name)) VIRTUAL
				ADD INDEX ix_fullname (full_name);

가상 칼럼이 VIRTUAL 이나 STORED 옵션으로 생성이 가능하다.

가상 칼럼은 테이블에 새로운 칼럼을 추가하는 것과 같은 효과를 내기 때문에 실제 테이블의 구조가 변경된다는 단점이 있다.

8.6.2 함수를 이용한 인덱스

테이블의 구조를 변경하지 않고 함수를 직접 사용하는 인덱스를 생성할 수 있다.

mysql> CREATE TABLE user (
					user_id BIGINT,
					first_name VARCHAR(10),
					last_name VARCHAR(10),
					PRIMARY KEY (user_id),
					INDEX ix_fullname((CONCAT(first_name, ' ', last_name)));
				);

함수를 직접 사용하는 인덱스는 테이블의 구조를 변경하지 않고, 계산된 결괏값의 검색을 빠르게 만들어 준다.

함수 기반 인덱스를 제대로 활용하려면 반드시 조건절에 함수 기반 인덱스에 명시된 표현식이 그대로 사용돼야 한다. 다를 경우 옵티마이저는 다른 표현식으로 간주하여 함수 기반 인덱스를 사용하지 못한다.

💡 가상 칼럼과 함수를 직접 이용하는 인덱스는 내부적으로 동일한 구현 방법을 사용한다. 내부적인 구현이 동일한 것이라 볼 수 있으며, 어떤 방법을 사용하더라도 둘의 성능차이는 발생하지 않는다는 것을 의미한다.

8.7 멀티 밸류 인덱스

전문 검색 인덱스를 제외한 모든 인덱스는 레코드 1건이 1개의 인덱스 키 값을 가진다. 하지만 멀티 밸류 인덱스는 하나의 데이터 레코드가 여러 개의 키 값을 가질 수 있는 형태의 인덱스다.

신용 정보 점수를 배열로 JSON 타입 컬럼에 저장하는 테이블을 가정해보자.

mysql> CREATE TABLE user (
					user_id BIGINT AUTO_INCREMENT PRIMARY KEY,
					first_name VARCHAR(10),
					last_name VARCHAR(10),
					credit_info JSON,
					INDEX mx_creditscores ( (CAST(credit_info->'$.credit_scores' AS UNSIGNED ARRAY)) )
				);

멀티 밸류 인덱스를 활용하기 위해서는 일반적인 조건 방식이 아닌, 반드시 다음 함수들을 이용해서 검색해야 옵티마이저가 인덱스를 활용한 실행 계획을 수립한다.

  • MEMBER OF()
  • JSON_CONTAINS()
  • JSON_OVERLAPS()
💡 MongoDB를 제대로 사용해 본적도 없고 멀티밸류라는 것을 처음 보아서 부족한 정리인거 같습니다. 혹시 잘 아시는 분이나 사용해보신 분이 계시다면 부연설명 해주시면 감사하겠습니다.

8.8 클러스터링 인덱스

클러스터링이란?

  • 여러 개를 하나로 묶는다는 의미

MySQL에서의 클러스터링은 테이블의 레코드를 비슷한 것(프라이머리 키를 기준으로)들끼리 묶어서 저장하는 형태로 구현하는데, 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에 착안한 것이다.

InnoDB 스토리지 엔진에서만 지원하며, 다른 스토리지 엔진에서는 지원되지 않는다.

8.8.1 클러스터링 인덱스

테이블의 프라이머리 키(PK)에만 적용되는 내용이며, PK 값이 비슷한 레코드끼리 묶어서 저장하는 것을 클러스터링 인덱스라고 표현한다.

**PK 값에 의해 레코드의 저장 위치가 결정된다.**

**PK 값이 변경된다면 그 레코드의 물리적인 저장 위치가 바뀌어야 한다는 것을 의미 한다.**

클러스터링 인덱스는 PK 값에 의해 레코드의 저장위치가 결정되므로 사실 인덱스 알고리즘이라기보다 테이블 레코드의 저장 방식 이라고 볼 수 있다.(클러스터링 인덱스 == 클러스터링 테이블)

InnoDB와 같이 항상 클러스터링 인덱스로 저장되는 테이블은 PK 기반의 검색이 매우 빠르며, 레코드의 저장이나 PK 변경이 상대적으로 느리다.

위와 같이 클러스터링 테이블 구조 자체는 일반 B-Tree와 비슷하지만 세컨더리 인덱스를 위한 B-Tree의 리프 노드와는 날리 클러스터링 인덱스의 리프 노드에는 레코드의 모든 칼럼이 같이 저장돼있다.

클러스터링 테이블에서 프라이머리 키를 변경하면 어떻게 될까?

mysql> UPDATE tb_table SET emp_no=100002 WHERE emp_no=100007;

  • 3번 페이지에 저장되어있던 100007이 100002로 바뀌며 2번 페이지로 이동했다.

PK 가 없는 InnoDB 테이블은 InnoDB 스토리지 엔진이 다음의 우선순위대로 PK 를 대체할 컬럼을 선택한다.

  1. PK 가 있으면 기본적으로 PK 를 클러스터링 키로 선택
  2. NOT NULL 옵션의 유니크 인덱스 중에서 첫 번째 인덱스를 클러스터링 키로 선택
  3. 자동으로 유니크한 값을 가지도록 증가되는 칼럼을 내부적으로 추가한 후, 클러스터링 키로 선택

적절한 클러스터링 키 후보를 찾지 못하는 경우 스토리지 엔진이 내부적으로 레코드의 일련번호 칼럼을 생성한다. 하지만 이는 사용자에게 노출되지 않으며, 쿼리 문장에 명시적으로 사용할 수 없다.

InnoDB 테이블에서 클러스터링 인덱스는 테이블당 단 하나만 가질 수 있는 엄청난 혜택 이므로 가능하다면 PK 를 명시적으로 생성하자!

8.8.2 세컨더리 인덱스에 미치는 영향

PK 가 세컨더리 인덱스에 미치는 영향을 알아보자.

InnoDB 테이블(클러스터링 테이블)의 모든 세컨더리 인덱스는 해당 레코드가 저장된 주소가 아닌, PK 값을 저장하도록 구현돼 있다.

employees 테이블에서 first_name 칼럼으로 검색하는 경우 PK 로 클러스터링된 InnoDB와 그렇지 않은 MyISAM에서 어떤 차이가 있는지 살펴보자.

mysql> CREATE TABLE employees (
					emp_no INT NOT NULL,
					first_name VARCHAR(10) NOT NULL,
					PRIMARY KEY (emp_no),
					INDEX ix_firstname (first_name)
				);

mysql> SELECT * FROM employees WHERE first_name='Aamer';
  • MyISAM: (1)ix_firstname 인덱스를 검색 (2)레코드의 주소 확인 (3)최종 레코드 가져옴
  • InnoDB: (1)ix_firstname 인덱스를 검색 (2)레코드의 PK 확인 (3)PK 인덱스를 검색 (4)최종 레코드

8.8.3 클러스터링 인덱스의 장점과 단점

클러스터링 되지 않은 일반 PK 와 클러스터링 인덱스를 비교했을 때 상대적인 장단점

장점

  • PK (클러스터링키)로 검색할 때 처리 성능이 매우 빠름(특히 범위검색)
  • 테이블의 모든 세컨더리 인덱스가 PK 를 가지고 있기 때문에 인덱스 만으로 처리될 수 있는 경우가 많음(커버링 인덱스)

단점

  • 테이블의 모든 세컨더리 인덱스가 클러스터링 키를 갖기 때문에 클러스터링 키 값의 크기가 클 경우 전체적으로 인덱스의 크기가 커짐
  • 세컨더리 인덱스를 통해 검색할 때 PK 로 다시 한번 검색해야 하므로 처리 성능이 느림
  • INSERT 할 때 PK 에 의해 레코드의 저장 위치가 결정되기 때문에 처리 성능이 느림
  • PK 를 변경할 때 레코드를 DELETE하고 INSERT하는 작업이 필요하기에 처리 성능이 느림

클러스터링 인덱스의 장점 - 빠른 R

클러스터링 인덱스의 단점 - 느린 CUD

일반적으로 웹 서비스와 같은 온라인 트랜잭션 환경에서는 쓰기와 일기의 비율이 2:8 에서 1:9 이기 때문에 빠른 R이 중요하다고 한다.

8.8.4 클러스터링 테이블 사용 시 주의사항

8.8.4.1 클러스터링 인덱스 키의 크기

모든 세컨더리 인덱스가 프라이머리 키 값을 포함하기에 프라이머리 키의 크기가 커지면 세컨더리 인덱스도 자동으로 크기가 커진다.

5개의 세컨더리 인덱스를 가지는 테이블의 프라이머리 키가 10바이트인 경우와 50바이트인 경우의 차이를 보면, 레코드 건수가 100만건일 경우 190MB 차이. 1000만건이 되면 1.9GB 차이가 난다.

또한 인덱스가 커질수록 같은 성능을 내기 위해 그만큼의 메모리가 더 필요해 지므로 InnoDB 테이블의 프라이머리 키는 신중하게 선택해야 한다.

8.8.4.3 프라이머리 키는 AUTO-INCREMENT보다는 업무적인 칼럼으로 생성

PK 로 검색하는 경우 클러스터링되지 않은 테이블에 비해 매우 빠르게 처리될 수 있다.

프라이머리 키는 그 의미 만큼이나 중요한 역할을 하기 때문에 대부분 검색에서 상당히 빈번하게 사용되는 것이 일반적이다. 설력 컬럼의 크기가 크더라도 업무적으로 해당 레코드를 대표할 수 있다면 그 칼럼을 PK로 설정하는 것이 좋다.

8.8.4.4 AUTO-INCREMENT 칼럼을 인조 식별자로 사용할 경우

여러 개의 칼럼이 복합으로 PK 가 만들어지는 경우 PK 의 크기가 길어질 때가 있다.

PK의 크기가 길어도 세컨더리 인덱스가 필요하지 않다면 그대로 PK를 사용하는 것이 좋다.

세컨더리 인덱스도 필요하고, PK의 크기도 길다면 AUTO INCREMENT 칼럼을 추가하고, 이를 PK로 설정하면 된다.

PK를 대체하기 위해 인위적으로 추가된 PK를 인조식별자(Surrogate key) 라고 한다.

조회보다 INSERT 위주의 테이블은 인조 식별자를 PK로 설정하는것이 성능 향상에 도움이 된다.

8.9 유니크 인덱스

유니크는 사실 인덱스라기보다는 제약 조건에 가깝다.

테이블이나 인덱스에 같은 값이 2개 이상 저장될 수 없음을 의미하는데, MySQL에서는 인덱스 없이 유니크 제약만 설정할 방법이 없다.

유니크 인덱스에는 NULL도 저장 가능하지만, NULL은 특정 값이 아니므로 2개 이상 저장 가능하다

8.9.1 유니크 인덱스와 일반 세컨더리 인덱스의 비교

유니크 인덱스와 유니크하지 않은 일반 세컨더리 인덱스는 인덱스의 구조상 아무런 차이가 없다.

8.9.1.1 인덱스 읽기

유니크 인덱스가 빠르다? (X)

유니크하지 않은 세컨더리 인덱스는 중복된 값이 허용되므로 읽어야 할 레코드가 많아서 느린 것이지 인덱스 자체의 특성 때문에 느린 것은 아니다.(성능은 비슷한데 양이 많아서 느리다는 뜻)

읽어야 할 레코드 건수가 같다면 성능상의 차이는 미미하다.

8.9.1.2 인덱스 쓰기

새로운 레코드가 INSERT 되거나 인덱스 칼럼의 값이 변경되는 경우, 인덱스 쓰기 작업이 필요하다.

유니크 인덱스의 키 값을 쓸 때는 중복된 값이 있는지 없는지 체크하는 과정이 한 단계 더 필요하기 때문에 유니크하지 않은 세컨더리 인덱스의 쓰기보다 느리다.

  • 유니크 인덱스에서 중복 값 체크시 읽기 잠금 사용
  • 유니크 인덱스에서 쓰기시 쓰기 잠금 사용
  • 이 과정에서 데드락이 아주 빈번히 발생한다(주의필요)

InnoDB 스토리지 엔진에서 인덱스 키의 저장을 버퍼링 하기 위해 체인지 버퍼가 사용되는데, 유니크 인덱스는 중복 체크를 해야 하므로 작업 자체를 버퍼링 하지 못하기 때문에 더 느리다.

8.9.2 유니크 인덱스 사용 시 주의사항

꼭 필요한 경우라면 유니크 인덱스를 생성하는 것은 당연하지만 불필요하게 유니크 인덱스를 생성하지 않는 것이 좋다.

  • MySQL의 유니크 인덱스는 다른 일반 인덱스와 같은 역할을 하므로 중복 생성할 필요가 없다.
  • PK와 유니크 인덱스를 동일하게 생성하는 것도 불필요한 중복이다.

결론적으로 유일성이 꼭 보장돼야 하는 칼럼에 대해서는 유니크 인덱스를 생성하되, 꼭 필요하지 않다면 유니크 인덱스보다는 유니크하지 않은 세컨더리 인덱스를 생성하는 방법도 고려해보자!

09 옵티마이저와 힌트

옵티마이저는 사용자의 요청으로 들어온 쿼리 문장을 저렴한 비용으로 가장 빠르게 처리할지를 결정하는 역할을 담당한는데, EXPLAIN이라는 명령으로 그 실행계획을 확인할 수 있다.

실행계획에 표시되는 내용을 제대로 이해하기 위해서는 MySQL 서버 옵티마이저가 실행하는 최적화에 대해 어느 정도 지식을 갖추고 있어야 한다.

9.1 개요

쿼리의 실행 계획을 수립하는 옵티마이저는 가장 복잡한 부분으로 알려져 있으며, 실행 계획을 이해하는 것 또한 상당히 어려운 일이다.

하지만 실행 계획을 이해할 수 있어야 불합리한 부분을 찾아내고 더 최적화된 방법으로 실행 계획을 수립하도록 유도할 수 있다.

9.1.1 쿼리 실행 절차

쿼리가 실행되는 과정은 크게 세 단계로 나눌 수 있다.

  1. 사용자로부터 요청된 SQL 문장을 잘게 쪼개서 MySQL 서버가 이해할 수 있는 수준으로 분리(파스 트리)한다.
    • MySQL 서버는 SQL 문장 그 잡채가 아니라 SQL 파스 트리를 이용해 쿼리를 실행한다.
  2. SQL의 파싱 정보(파스 트리)를 확인하면서 어떤 테이블로부터 읽고 어떤 인덱스를 이용해 테이블을 읽을지 선택한다.
    • 파스 트리를 참조하면서 다음의 내용을 처리한다.
      • 불필요한 조건 제거
      • 복잡한 연산의 단순화
      • 여러 테이블의 조인이 있는 경우 어떤 순서로 테이블을 읽을지 결정
      • 각 테이블에 사용된 조건과 인덱스 통계 정보를 이용하여 사용할 인덱스 결정
      • 가져온 레코드들을 임시 테이블에 넣고 다시 한번 가공해야 하는지 결정
    • 이 단계는 최적화 및 실행 계획 수립단계이며 옵티마이저에서 처리
    • 이 단계가 완료되면 쿼리의 실행 계획이 만들어진다.
  3. 두 번째 단계에서 결정된 테이블의 읽기 순서나 선택된 인덱스를 이용해 스토리지 엔진으로부터 데이터를 가져온다.
    • MySQL 엔진과 스토리지 엔진이 동시에 참여해서 처리

9.1.2 옵티마이저의 종류

옵티마이저는 크게 현재 대부분의 DBMS가 선택하고 있는 비용 기반 최적화(Cost-based Optimizer, CBO) 방법과 초기 버전 오라클에서 많이 사용했던 규칙 기반 최적화 방법(Rule-based optimizer, RBO)로 나눌 수 있다.

  1. 비용 기반 최적화(Cost-based Optimizer, CBO)
    • 기본적으로 대상 테이블의 레코드 건수나 선택도 등을 고려하지 않고 옵티마이저에 내장된 우선순위에 따라 실행 계획을 수립하는 방식
    • 통계정보를 조사하지 않고 실행계획이 수립되기 때문에 같은 쿼리에 대해서는 항상 같은 실행 방법을 만들어낸다.
    • 하지만 사용자의 데이터는 분포도가 매우 다양하기 때문에 오래전부터 거의 사용되지 않는 방식이다.
  2. 규칙 기반 최적화 방법(Rule-based optimizer, RBO)
    • 쿼리를 처리하기 위한 여러가지 가능한 방법을 만들고 각 단위 작업의 비용(부하) 정보와 대상 테이블의 예측된 통계 정보를 이용해 실행 계획별 비용을 산출한다.
    • 산출된 실행 방법별로 비용이 최소로 소요되는 처리 방식을 선택해 최종적으로 쿼리 실행
    • 현재 대부분의 RDBMS가 비용 기반의 옵티마이저를 채택하고 있고 MySQL도 비용 기반 옵티마이저를 채택하고 있다.
profile
백엔드 프로그래머

0개의 댓글