kykapple
yeongkeeDev
kykapple
Github
  • 분류 전체보기
    • Frontend
    • Backend
      • Spring
      • JPA
    • DevOps
    • Computer Science

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Adaptive Hash Index
  • index
  • nGrinder
  • Redis
  • spring rest docs
  • Dynamic Proxy
  • 도커 스웜
  • JPA
  • IP
  • Index condition pushdown
  • 도커
  • 의존관계 주입
  • 성능 개선
  • aop
  • 인덱스
  • 다이내믹 프록시
  • Jenkins
  • Cache
  • 트랜잭션 전파
  • 인덱스 컨디션 푸시다운
  • Transaction Propagation
  • docker
  • Transaction
  • 트랜잭션
  • CIDR
  • Di
  • 어댑티브 해시 인덱스
  • QueryCounter
  • Process
  • Dokcer Swarm

최근 글

티스토리

kykapple

yeongkeeDev

인덱스 컨디션 푸시다운(index_condition_pushdown)
DevOps

인덱스 컨디션 푸시다운(index_condition_pushdown)

2022. 2. 19. 16:22

인덱스 컨디션 푸시다운

인덱스 컨디션 푸시다운이란 인덱스 조건(Codition)을 스토리지 엔진으로 전달해주는 기능이다.

MySQL 5.6 버전부터 해당 기능이 도입되었는데, 어떠한 이점을 가져오는지 알아보도록 하자.

 

테이블 및 인덱스 생성

우선 인덱스 컨디션 푸시다운을 테스트하기 위해 employees 테이블을 생성해서 100건 정도의 데이터를 넣고, 아래와 같은 인덱스를 생성해주도록 한다.

CREATE TABLE employees (emp_no bigint not null primary key, first_name varchar(255), last_name varchar(255), hire_date datetime);
ALTER TABLE employees ADD INDEX temp_idx (last_name, first_name);

 

인덱스 컨디션 푸시다운 비교

우선 MySQL 옵티마이저 스위치 옵션에서 인덱스 컨디션 푸시다운 옵션을 껐을 때의 쿼리 실행 계획을 살펴보도록 하자.

SET optimizer_switch='index_condition_pushdown=off';
SHOW VARIABLES LIKE 'optimizer_switch';
Variable_name      Value
optimizer_switch   ..., index_condition_pushdown=off,...

그리고 다음과 같은 쿼리를 실행할 때 스토리지 엔진이 몇 건의 레코드를 읽는 지 알아보도록 하자.

SELECT * FROM employees WHERE last_name='Taylor' AND first_name LIKE '%Winston';

앞서 (last_name, first_name) 으로 인덱스를 생성하였기 때문에 WHERE 절의 last_name='Taylor' 조건은 temp_idx 인덱스를 레인지 스캔으로 사용할 수 있다. 하지만 first_name LIKE '%Winston' 조건은 와일드카드로 시작되는 LIKE 절이므로 인덱스가 적용되지 않기 때문에 위 쿼리는 last_name='Taylor' 조건으로 레코드들을 조회한 뒤, first_name LIKE '%Winston' 조건에 맞는 레코드인지 하나씩 비교해보아야 한다.

따라서 last_name='Talyor' 인 레코드들을 모두 읽어와야 한다는 것을 알 수 있다.

 

실제로 쿼리의 실행 계획을 확인해보면 다음과 같다.

EXPLAIN SELECT * FROM employees WHERE last_name='Taylor' AND first_name LIKE '%Winston';

Extra 컬럼에 "Using where" 이 나타나는 것을 알 수 있는데, 이는 InnoDB 스토리지 엔진이 읽어서 반환해준 레코드가 인덱스를 사용할 수 없는 WHERE 조건에 일치하는지 검사하는 과정을 의미한다.

여기서는 InnoDB 스토리지 엔진이 반환해준 last_name='Taylor' 인 레코드들 중에서 first_name LIKE '%Winston' 조건에 맞는 레코드를 검사하는 과정을 의미하게 된다.

 

그런데 만약 last_name='Taylor' 인 레코드가 1만 건이고, 그 중 단 1건만 first_name LIKE '%Winston' 조건에 일치한다면 어떨까? 이 경우에는 9,999건의 레코드 읽기가 불필요한 작업이 된다.

또 여기서 한 번 더 생각해보면 first_name LIKE '%Winston' 조건을 처리하기 위해 이미 last_name='Taylor' 조건을 통해 읽은 temp_idx 인덱스의 first_name 컬럼을 이용하지 않고, 테이블의 레코드를 읽어서 비교하는 이유가 궁금해질 수 있다.

 

이는 MySQL 5.5 버전까지는 인덱스를 범위 제한 조건으로 사용하지 못하는 first_name LIKE '%Winston' 과 같은 조건을 MySQL 엔진이 스토리지 엔진으로 아예 전달해주지 않았기 때문이다. 그래서 스토리지 엔진에서는 last_name='Taylor' 조건에 맞는 레코드를 모두 읽을 수 밖에 없게 되는 것이다.

 

하지만 MySQL 5.6 버전부터는 이렇게 범위 제한 조건으로 사용하지 못하는 조건이라도 인덱스에 포함된 컬럼이라면 모두 스토리지 엔진에 전달해서 꼭 필요한 레코드들만 읽을 수 있도록 개선되었다. (인덱스 컨디션 푸시다운의 도입)

 

이번에는 인덱스 컨디션 푸시다운 옵션을 키고, 동일한 쿼리의 실행 계획을 살펴보도록 하자.

SET optimizer_switch='index_condition_pushdown=on';
SHOW VARIABLES LIKE 'optimizer_switch';
Variable_name      Value
optimizer_switch   ..., index_condition_pushdown=on,...
EXPLAIN SELECT * FROM employees WHERE last_name='Taylor' AND first_name LIKE '%Winston';

위와 같이 옵티마이저 스위치에서 index_condition_pushdown을 활성화하고 쿼리의 실행 계획을 살펴보면 Extra 컬럼에 "Using where" 가 아닌 "Using index condition" 이 나타나는 것을 확인할 수 있다.

이제는 인덱스 조건을 이용해 스토리지 엔진에서 최대한 필터링한 데이터만 MySQL 엔진으로 전달할 수 있게 된다.

 

Reference

Real MySQL

'DevOps' 카테고리의 다른 글

Jenkins를 활용한 자동 배포 구축  (0) 2022.05.13
어댑티브 해시 인덱스(Adaptive Hash Index)  (0) 2022.02.02
도커 스웜(Docker Swarm) 알아보기  (0) 2021.12.26
Docker란 무엇인가  (0) 2021.12.20
    kykapple
    kykapple

    티스토리툴바