mariadb optimization

131
Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee Blog : http://ora-sysdba.tistory.com/ 1 MariaDB : Optimization Jong Jin Lee SYS4U I&C EC Solution Lab / Software Engineer

Upload: jongjin-lee

Post on 26-Jan-2015

139 views

Category:

Data & Analytics


5 download

DESCRIPTION

*If you see the screen is not good condition, downloading please.* MariaDB Optimization - 풀 테이블 스캔 - ORDER BY 처리(Using filesort) - GROUP BY 처리 - DISTINCT 처리 - 임시 테이블(Using Tempoary) - 인덱스 컨디션 푸시다운(Index Condition Pushdown, ICP) - 멀티 레인지 리드(Multi Range Read) - 인덱스 머지(Index merge) - 테이블 조인 - 서브 쿼리

TRANSCRIPT

Page 1: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

1

MariaDB : Optimization

Jong Jin Lee

SYS4U I&C EC Solution Lab / Software Engineer

Page 2: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

2

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 3: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

3

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 4: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

4

MariaDB : 풀테이블스캔

B-Tree Index Table Data

SCAN

Result Data

B-Tree Index Table Data

Result Data

FTS(Full Table Scan) Index Table Scan

Page 5: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

5

MariaDB : 풀테이블스캔

풀테이블스캔의원인(MyISAM Engine) 인덱스를통해읽는것보다풀테이블스캔이더빠른경우 WHERE 절이나 ON 절에인덱스가적절하지않는경우 인덱스레인지스캔을사용하더라도옵티마이저가판단한조건일치레코드건수가너무많은경우

InnoDB, XtraDB Engine의경우 연속된데이터페이지를읽으면백그라운드스레드에의해리드어헤드(Read ahead) 작업이자동으로시작됨

시스템변수 “innodb_read_ahead_threshold”로 설정(read ahead 시점)

Page 6: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

6

MariaDB : 풀테이블스캔

리드어헤드(Read ahead)

SELECT *

FROM

EMP

WHERE

EMPNO

LIKE”1%”

스레드

forground Thread

XtraDB

Buffer Pool

XtraDB

4 page, 8 page 최대 64 page까지Bufferpool에 저장

Background Thread

Page 7: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

7

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 8: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

8

ORDER BY 처리방식에따른장/단점

MariaDB : ORDER BY 처리(Using filesort)

장점 단점

인덱스이용 - DML쿼리가 실행될때이미인덱스가정렬돼있어서순서대로읽기만하면된다.(속도가 빠름)

- DML 작업시부가적인인덱스추가/삭제작업이필요하므로느리다.

- 인덱스공간때문에디스크이슈가발생한다.

- 인덱스개수여부에따라 InnoDB 버퍼풀이나,

MyISAM 캐쉬용메모리가 많이필요하다.

Filesort 이용 - 인덱스를생성하지않아도되므로인덱스를 이용할때의단점이장점으로바뀜.

- 정렬해야할레코드가 많지않으면메모리에서 처리가능하므로, 속도가빠르다.

- 정렬작업이쿼리실행시처리되므로 레코드대상건수가많아질수록쿼리의응답속도가느리다.

Page 9: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

9

MariaDB : ORDER BY 처리(Using filesort)

소트버퍼(Sort Buffer) MariaDB 기본적으로내부임시테이블은 Aria 스토리지엔진사용 “sort_buffer_size” 환경변수로소트버퍼의공간설정가능.

소트버퍼는세션메모리영역이므로커넥션이많을수록, 정렬작업이많을수록메모리부족현상이발생한다.

소트버퍼크기는 256KB ~ 512KB 사이가최적의성능.(각자환경에따라차이가발생할수있음)

Page 10: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

10

MariaDB : ORDER BY 처리(Using filesort)

소트버퍼(Sort Buffer)

SORT BUFFERCLIENT DB(Disk)

버퍼의 레코드 정렬 디스크의 정렬된레코드 병합

정렬된 버퍼를디스크에 임시 저장

멀티 머지 작업(Multi-Merge)

Page 11: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

11

MariaDB : ORDER BY 처리(Using filesort)

정렬알고리즘 레코드를정렬할때레코드전체를소트버퍼에담을지또는정렬기준칼럼만소트버퍼에담을지에따라 2가지알고리즘으로나뉜다.

싱글패스알고리즘은정렬대상레코드의크기가건수가작은경우빠른성능을보이며, 투패스알고리즘은정렬대상레코드의크기나건수가상당히많을경우효율적이라고볼수있다.

Page 12: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

12

MariaDB : ORDER BY 처리(Using filesort)

정렬알고리즘 (Single Pass)

쿼리 실행

레코드 정렬

Multi-merge

디스크(Temporary Files)

테이블(데이터 파일)

emp_no,

first_name,

last_name

SELECT empno, first_name, last_name

FROM employees

ORDER BY first_name

정렬 결과

Page 13: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

13

정렬알고리즘 (Tow Pass)

MariaDB : ORDER BY 처리(Using filesort)

쿼리 실행

레코드 정렬

Multi-merge

디스크(Temporary Files)

테이블(데이터 파일)

emp_no,

first_name

SELECT empno, first_name, last_name

FROM employees

ORDER BY first_name

정렬 결과

정렬 순서대로 last_name 컬럼을 읽어서 최종 결과 생성

추가로 필요한 last_name 추출

Page 14: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

14

MariaDB : ORDER BY 처리(Using filesort)

정렬의처리방식

정렬처리방법 실행계획의 Extra 코멘트

인덱스사용한정렬 - 별도의내용표기없음

드라이빙테이블만정렬(조인이없는경우포함) - “Using filesort”가표시됨

조인결과를임시테이블로저장한후,

임시테이블에서정렬- “Using temporary; Using filesort”가같이표시됨

Page 15: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

15

MariaDB : ORDER BY 처리(Using filesort)

인덱스를사용한정렬 order by에명시된칼럼이제일먼저읽는테이블(조인이사용된경우드라이빙테이블)에속하고, order by의순서대로생성된인덱스가있어야한다.

또한 where 절에첫번째읽는테이블의칼럼에대한조건이있다면, 그조건과 order by는같은인덱스를사용할수있어야한다.

B-Tree 계열이아닌, 해시인덱스나전문검색인덱스등에서는인덱스정렬이불가하다.

여러테이블일경우에는 N-L Join 방식에서만사용가능하다.

Page 16: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

16

MariaDB : ORDER BY 처리(Using filesort)

인덱스를사용한정렬

select *

from employees e, salaries s

where s.emp_no=e.emp_no

and e.emp_no between 100002 and 100020

order by e.emp_no;

emp_no first_name …

10001 Jasminko …

10002 Claudi …

10003 Marsja …

10004 Anneke …

emp_no from_date …

10001 2014-07-14 …

10001 … …

10002 … …

10002 … …

10002 … …

10003 … …

10003 … …

10004 … …Order by (Index)

ORDER BY 절=>

성능이슈없음!

Salaries Table

Employees Table

Page 17: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

17

MariaDB : ORDER BY 처리(Using filesort)

드라이빙테이블만정렬 드라이빙테이블의레코드를먼저정렬한다음조인을실행하는것이모든조인결과를통째로정렬하는것보다효율적이다.

조인에서드라이빙테이블의칼럼만으로 order by 절이작성돼야한다.

select *

from employees e, salaries s

where s.emp_no=e.emp_no

and e.emp_no between 100002 and 100010

order by e.last_name

Page 18: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

18

MariaDB : ORDER BY 처리(Using filesort)

드라이빙테이블만정렬

emp_no first_name …

10001 Jasminko …

10002 Claudi …

10003 Marsja …

10004 Anneke …

emp_no from_date …

10001 2014-07-14 …

10001 … …

10002 … …

10002 … …

10002 … …

10003 … …

10005 … …

10007 … …emp_no first_name …

10010 … …

10007 … …

10005 … …

10004 … …

SortBuffer & Salaries

table Join

Copy to SortBuffer &

Order by

Salaries Table

Employees Table

Page 19: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

19

MariaDB : ORDER BY 처리(Using filesort)

임시테이블을이용한정렬 “드라이빙테이블만정렬” 의경우만제외하고는, 항상조인의결과를임시테이블에저장하고, 그결과를다시정렬하는과정을거친다.

select *

from employees e, salaries s

where s.emp_no=e.emp_no

and e.emp_no between 100002 and 100010

order by s.salary;

Page 20: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

20

MariaDB : ORDER BY 처리(Using filesort)

임시테이블을이용한정렬

emp_no first_name …

10001 Jasminko …

10002 Claudi …

10003 Marsja …

10004 Anneke …

emp_no from_date …

10001 2014-07-14 …

10001 … …

10002 … …

10002 … …

10002 … …

10003 … …

10003 … …

10004 … …

Salaries Table

Employees Table

emp_no first_name …

10010 … …

10007 … …

10005 … …

10004 … …

임시 테이블의 정렬임시 테이블

Page 21: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

21

MariaDB : ORDER BY 처리(Using filesort)

정렬방식의성능비교 ORDER BY 나 GROUP BY 같은작업은 WHERE절조건에만족하는레코드를 LIMIT 건수만큼만가져와서는처리될수없다.

WHERE 절조건이아무리인덱스를잘활용하도록튜닝해도잘못된ORDER BY나 GROUP BY 때문에쿼리가느려지는경우가자주발생한다.

왜느려질까? > 쿼리가처리되는방식 (스트리밍처리, 버퍼링처리)

가능하다면인덱스를사용한정렬로유도하고,

그렇지못하다면최소한드라이빙테이블만정렬해도되는수준으로튜닝!

Page 22: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

22

스트리밍처리(Streaming) 방식

MariaDB : ORDER BY 처리(Using filesort)

클라이언트 서버

Page 23: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

23

버퍼링처리(Buffering) 방식

MariaDB : ORDER BY 처리(Using filesort)

클라이언트 서버버퍼링 후 일괄 처리

Page 24: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

24

MariaDB : ORDER BY 처리(Using filesort)

ORDER BY .. LIMIT n 최적화 ORDER BY 절을가진쿼리가인덱스를사용하지못할때 => 실시간정렬(Using filesort)를수행한다.

이때에는조건절에일치하는레코드들을모두가져와소트버퍼를이용해서 Quick Sort 알고리즘을수행한다.

만약정렬대상레코드가너무많으면소트버퍼크기만큼레코드를모아정렬하고다시병합하는(Sort_merge_pass)과정을거쳐야한다.

=> CPU, DISK I/O 증가

Page 25: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

25

MariaDB : ORDER BY 처리(Using filesort)

ORDER BY .. LIMIT n 최적화

emp_no first_name last_name

INT VARCHAR(14) VARCHAR(16)

… … …

… … Toto

… … Matt

select emp_no, first_name, last_name

from employees

where emp_no between 10001 and 10900

order by last_name limit 10;

… … Matt

… … Toto

테이블정렬된 결과

우선순위 큐(Priority Queue)

SortBuffer = 256KB레코드당 최대 124 바이트(4 + (14x4) + (16x4))

LIMIT n으로 가져가는 레코드의 바이트 크기가우선순위 큐가 만들어지는 소트 버퍼의 크기보다 작은 경우에만 최적화가 적용 가능하다.

Page 26: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

26

MariaDB : ORDER BY 처리(Using filesort)

정렬관련상태변수

Variable Name Description

Sort_merge_passesThe number of merge passes that the sort algorithm has had to do. If this value is large, you should

consider increasing the value of the sort_buffer_size system variable.

Sort_range The number of sorts that were done using ranges.

Sort_rows The number of sorted rows.

Sort_scan The number of sorts that were done by scanning the table.

멀티 머지 처리 횟수

인덱스 레인지 스캔을 통해검색된 결과에 대한 정렬 작업 횟수

풀 테이블 스캔을 통해검색된 결과에 대한 정렬 작업 횟수

지금까지 정렬한 전체 레코드 건수

Page 27: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

27

MariaDB : ORDER BY 처리(Using filesort)

정렬관련상태변수

MariaDB [employees]> show session status like 'Sort%';

+-------------------+--------+

| Variable_name | Value |

+-------------------+--------+

| Sort_merge_passes | 0 |

| Sort_range | 0 |

| Sort_rows | 0 |

| Sort_scan | 0 |

+-------------------+--------+

4 rows in set (0.01 sec)

MariaDB [employees]> select first_name,

last_name

from employees

group by first_name, last_name;

MariaDB [employees]> show session status like 'Sort%';

+-------------------+--------+

| Variable_name | Value |

+-------------------+--------+

| Sort_merge_passes | 1 |

| Sort_range | 0 |

| Sort_rows | 279408 |

| Sort_scan | 1 |

+-------------------+--------+

4 rows in set (0.01 sec)

Page 28: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

28

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 29: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

29

MariaDB : GROUP BY 처리

GROUP BY GROUP BY 작업도인덱스를사용하는경우와그렇지못한경우로나눌수있다.

인덱스를사용할때는인덱스를차례대로이용하는인덱스스캔방법과인덱스를건너뛰면서읽는루스인덱스스캔방법으로나뉜다.

그리고인덱스를사용하지못하는쿼리에서 GROUP BY 작업은임시테이블을이용한다.

Page 30: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

30

MariaDB : GROUP BY 처리

인덱스스캔을이용하는 GROUP BY(타이트인덱스스캔) GROUP BY가인덱스를사용해서처리된다하더라도그룹함수(Aggregation function) 등의그룹값을처리하기위해임시테이블이필요하다.

GROUP BY가인덱스를통해처리되는쿼리는이미정렬된인덱스를읽는것이므로, 추가적인정렬작업이필요하지않다.

이런그룹핑방식을사용하는쿼리는실행계획에서는 Extra 칼럼에별도로 Using index for group-by, Using temporary, Using filesort 등이표시되지않는다.

Page 31: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

31

MariaDB : GROUP BY 처리

루스(loose) 인덱스스캔을이용하는 GROUP BY 루스인덱스스캔은단일테이블에대해수행되는 GROUP BY 처리에만사용할수있다.

프리픽스인덱스(Prefix index)는루스인덱스스캔에사용할수없다.

인덱스레인지스캔에서는유니크한값의수가많을수록성능향상이되는반면, 루스인덱스스캔에서는인덱스의유니크한값의수가적을수록성능이향상된다.

즉, 분포도가좋지않은인덱스일수록성능에효과적이다.

Page 32: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

32

MariaDB : GROUP BY 처리

루스(loose) 인덱스스캔을이용하는 GROUP BY

select emp_no

from salaries

where from_date='1985-03-01' #(emp_no=10001 and from_date ‘1985-03-01’)

group by emp_no;

버전업에 따라서 최적화 방법이 향상됨

1. (emp_no + from_date) index를 scan하여 emp_no의유일한값(그룹키) “10001”을찾아낸다.

2. emp_no가 “10001”인것중에서 from_date 값이 ‘1985-03-01’인레코드만추출한다.

이단계에서암묵적조건절변환이벌어진다.(emp_no=10001 and from_date ‘1985-03-01’)

3. (emp_no + from_date) 인덱스에서 emp_no의그다음유니크값을가져온다.

4. 3번단계에서결과가더없으면처리를종료하고, 아니면반복수행한다.

Page 33: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

33

MariaDB : GROUP BY 처리

임시테이블을사용하는 GROUP BY GROUP BY의기준칼럼이드라이빙테이블에있든드리븐테이블에있든관계없이인덱스를전혀사용하지못할때이방식이사용된다.

select e.last_name, avg(s.salary)

from employees e, salaries s

where s.emp_no=e.emp_no

group by e.last_name;

1. Employees 테이블을 풀테이블스캔한다.

2. 1 단계에서읽은 employees 테이블의 emp_no 값을이용해 salaries 테이블을 scan 한다.

3. 2 단계에서얻은조인결과레코드를임시테이블에저장한다. (이때, 원본쿼리의 GROUP

BY 절에사용된컬럼과 SELECT 컬럼만저장, GROUP BY 절에사용된칼럼으로유니크키생성, 즉 GROUP BY가임시테이블로처리되면 임시테이블은항상유니크키를가진다.)

4. 1 ~ 3 단계까지조인완료시점까지반복한다. 완료되면유니크키순으로클라이언트에전송한다. 만약, ORDER BY 절에명시된컬럼과같으면정렬작업이 발생하지않지만,

상이하면 Filesort 과정을거쳐한번더정렬작업을 수행한다.

Page 34: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

34

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 35: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

35

MariaDB : DISTINCT 처리

DISTINCT 처리 특정칼럼의유니크한값만을조회하려면 SELECT 쿼리에 DISTINCT를사용한다.

DISTINCT는 MIN(), MAX(), COUNT()와같은집합함수를함께사용하는경우와집합함수가없는경우두가지로구분되고이두가지의경우는각각 DISTINCT 키워드가영향을미치는범위가달라진다.

Page 36: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

36

MariaDB : DISTINCT 처리

SELECT DISTINCT … GROUP BY와거의동일한방식으로처리되지만, 정렬이보장되지않는다는것이차이점이다.

DISTINCT는함수가아니므로그뒤의괄호는의미가없다.

MariaDB 서버는 DISTINCT 뒤의괄호를그냥의미없이사용된괄호로해석하고제거해버린다.

select DISTINCT emp_no from salaries;

select emp_no from salaries group by emp_no;동일한 쿼리

select DISTINCT first_name, last_name from salaries;

select DISTINCT (first_name), last_name from salaries;동일한 쿼리

Page 37: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

37

MariaDB : DISTINCT 처리

집합함수와함께사용된 DISTINCT SELECT DISTINCT와다른형태로, 집합함수의인자로전달된칼럼값이유니크한것들만가져온다.

select count(distinct s.salary), count(distinct e.last_name)

from employees e, salaries s

where e.emp_no=s.emp_no

and e.emp_no between 100001 and 100100;

각 연산 값을 저장하기 위한 임시 테이블을 만들어서 사용

select count(distinct emp_no) from employees;

select count(distinct emp_no) from dept_emp group by dept_no;

인덱스된 칼럼에 대해 DISTINCT 처리를 수행할 때는 인덱스를 풀 스캔하거나,

레인지 스캔을 하여 임시 테이블 없이 수행 가능하다.

Optimization

Page 38: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

38

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 39: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

39

MariaDB : 임시테이블(Using temporary)

임시테이블(Using temporary) 여기서이야기하는임시테이블은 “CREATE TEMPORARY TABLE”과는다른 MariaDB 에서이루어지는 “내부적” 임시테이블이다.

MariaDB는 MySQL과 Percona Server와달리 Aria Storage Engine을기본으로사용한다. (MySQL, Percona Server -> MyISAM Storage Engine)

MariaDB 엔진이내부적으로가공생성하는임시테이블은다른세션, 다른쿼리에서볼수없다.

내부적인임시테이블은쿼리처리완료시점에자동삭제된다.

Page 40: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

40

MariaDB : 임시테이블(Using temporary)

임시테이블이필요한쿼리 ORDER BY와 GROUP BY에명시된칼럼이다른쿼리 ORDER BY나 GROUP BY에명시된조인의순서상첫번째테이블이아닌쿼리

DISTINCT와 ORDER BY가동시에쿼리에존재하는경우또는DISTINCT가인덱스로처리되지못하는쿼리

UNION이나 UNION DISTINCT가사용된쿼리(select_type 칼럼이 UNION

RESULT인경우)

UNION ALL이사용된쿼리(select_type 칼럼이 UNION RESULT인경우)

쿼리의실행계획에서 select_type이 DERIVED인쿼리

Extra 칼럼에 “Using temporary”인 키워드가 표시된다.

1 ~ 4 패턴은 유니크 인덱스를 가지는 내부 임시 테이블5 ~ 6 패턴은 인덱스가 없는 내부 임시 테이블4 ~ 6 “Using temporary”가 표시되지 않을 때도 임시 테이블을 사용하는 경우

Page 41: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

41

MariaDB : 임시테이블(Using temporary)

임시테이블이디스크에생성되는경우(Aria 스토리지엔진) 임시테이블에저장해야하는내용중 BLOB(Binary Large Object)나

TEXT와같은대용량컬럼이있는경우 임시테이블에저장해야하는레코드의전체크기나 UNION이나 UNION

ALL에서 SELECT 되는칼럼중에서길이가 512바이트이상인크기의칼럼이있는경우

GROUP BY나 DISTINCT 칼럼에서 512바이트이상인크기의칼럼이있는경우

임시테이블에저장할데이터의전체크기(데이터의바이트크기)가mp_table_size 또는 max_heap_table_size 시스템변수값보다큰경우

1 ~ 3 패턴은 처음부터 디스크에 Aria 스토리지 엔진을 사용해서 내부 임시 테이블이 만들어지는 경우4 패턴은 MEMORY 스토리지 엔진을 이용해 메모리에 내부 임시 테이블이 생성되지만 테이블의 크기가 시스템 설정 값을 넘어서는 순간 디스크에 Aria 테이블로 변환된다.

Page 42: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

42

MariaDB : 임시테이블(Using temporary)

임시테이블관련상태변수

Variable Name Description

Created_tmp_disk_tables

The number of internal on-disk temporary tables created by the server while executing statements.

If an internal temporary table is created initially as an in-memory table but becomes too large,

MySQL automatically converts it to an on-disk table. The maximum size for in-memory temporary

tables is the minimum of the tmp_table_size and max_heap_table_size values. If

Created_tmp_disk_tables is large, you may want to increase the tmp_table_size or

max_heap_table_size value to lessen the likelihood that internal temporary tables in memory will

be converted to on-disk tables.

You can compare the number of internal on-disk temporary tables created to the total number of

internal temporary tables created by comparing the values of the Created_tmp_disk_tables and

Created_tmp_tables variables.

Created_tmp_tables

The number of internal temporary tables created by the server while executing statements.

You can compare the number of internal on-disk temporary tables created to the total number of

internal temporary tables created by comparing the values of the Created_tmp_disk_tables and

Created_tmp_tables variables.

쿼리의 처리를 위해 만들어진 내부 임시테이블 개수를 누적하는 상태 값(메모리, 디스크 생성 구분 않고 누적 깂)

디스크에 내부 임시 테이블이 만들어진개수만 누적해서 가지고 있는 상태 값

Page 43: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

43

MariaDB : 임시테이블(Using temporary)

임시테이블관련상태변수

MariaDB [employees]> show session status like 'Sort%';

+-------------------+--------+

| Variable_name | Value |

+-------------------+--------+

| Sort_merge_passes | 0 |

| Sort_range | 0 |

| Sort_rows | 0 |

| Sort_scan | 0 |

+-------------------+--------+

4 rows in set (0.01 sec)

MariaDB [employees]> select first_name,

last_name

from employees

group by first_name, last_name;

MariaDB [employees]> show session status like 'Sort%';

+-------------------+--------+

| Variable_name | Value |

+-------------------+--------+

| Sort_merge_passes | 1 |

| Sort_range | 0 |

| Sort_rows | 279408 |

| Sort_scan | 1 |

+-------------------+--------+

4 rows in set (0.01 sec)

Page 44: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

44

MariaDB : 임시테이블(Using temporary)

인덱스를가지는내부임시테이블 MariaDB 5.3 버전부터 MariaDB 엔진이쿼리의특성을분석하여자동으로인덱스를추가한상태로생성할수있도록개선되었다.

select * from

(select dept_name from departments group by dept_name) x,

(select dept_name from departments group by dept_name) y

where x.dept_name=y.dept_name;

(x)(y)

dept_name 칼럼에 인덱스 생성 확인

Page 45: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

45

MariaDB : 임시테이블(Using temporary)

내부임시테이블(Internal Temporary Table)의주의사항

select * from employees group by last_name order by first_name;

1. 처음부터임시테이블이필요하지않게만드는것이가장좋다.

2. 가능하다면 인덱스를이용하여처리하라.

3. 내부임시테이블이메모리에만저장될수있게가공대상레코드를적게만들어라.

4. 가공해야할데이터를 줄일수없으면 tmp_table_size 또는 max_heap_table_size 변수를무조건크게설정해라.

MEMORY(HEAP) 테이블로 물리 메모리에 생성되는 경우, 모든 칼럼은 고정 크기 칼럼이다.

ex) first_name = 512 * 3 (UTF8 이라 가정)

>> select 컬럼 최소화, 칼럼 데이터 선정은 최대한 작게.

Page 46: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

46

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 47: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

47

MariaDB : 인덱스컨디션푸시다운

인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

alter table employees add index ix_lastname_firstname (last_name, first_name);

set optimizer_switch='index_condition_pushdown=off';

select * from employees where last_name='Action' and first_name like'%sal';

last_name=‘Action’ 조건으로인덱스레인지스캔을하고 first_name LIKE ‘%sal’ 조건을비교하였다.

실제테이블을읽어서 3건의레코드를가져왔지만, 그중에단 1건만 first_name LIKE ‘%sal’ 조건에일치했다.

last_name=‘Action’ 조건에맞는레코드가 10만건이라면?

MariaDB 5.3 or MySQL 5.6 Over

Page 48: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

48

MariaDB : 인덱스컨디션푸시다운

인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

last_name first_name

… …

… …

… …

Action …

Action …

Action …

… …

emp_no birth_date first_name last_name gender hire_date

219052 1965-01-06 Marsal Action F 1995-08-02

… … … … … …

429125 1961-07-19 Marsja Action M 1991-09-05

… … … … … …

442803 1957-04-21 Masaki Action M 1992-11-26

… … … … … …

ix_last_name_first_name 인덱스의 first_name 칼럼을이용하지 않고, 다시테이블레코드를읽어서처리했다면?

Page 49: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

49

MariaDB : 인덱스컨디션푸시다운

인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

set optimizer_switch='index_condition_pushdown=on';

select * from employees where last_name='Action' and first_name like'%sal';

Page 50: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

50

MariaDB : 인덱스컨디션푸시다운

인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

last_name first_name

… …

… …

… …

Action …

Action …

Action …

… …

emp_no birth_date first_name last_name gender hire_date

219052 1965-01-06 Marsal Action F 1995-08-02

… … … … … …

429125 1961-07-19 Marsja Action M 1991-09-05

… … … … … …

442803 1957-04-21 Masaki Action M 1992-11-26

… … … … … …

인덱스의 first_name 칼럼을이용해서비교했다면, 불필요한 2건의레코드는테이블에서 읽지않아도된다.

인덱스를이용해서최대한필터링까지 완료해서꼭필요한레코드 1건에대해서만테이블읽기를수행한다.

Extra 필드에는 “Using Where”가 없어지고 “Using index condition”이 출력된다.

Page 51: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

51

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 52: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

52

MariaDB : 멀티레인지리드(MRR)

멀티레인지리드(Multi Range Read) 전통적 RDBMS에서는인덱스스캔을통해대상레코드범위를스캔하고,

실제데이터파일을읽는작업은랜덤 I/O를동반한다.

MariaDB에서는이런랜덤디스크 I/O를줄이기위해서멀티레인지리드라는최적화기법을사용한다.

MariaDB 5.3 or MySQL 5.6 Over

Page 4

index recode recode address

Aamer 11800

… …

Page 5

index recode recode address

… …

… …

인덱스 리프 노드 MRR 버퍼

index recode recode address

… …

… …

… …

… …

… …

데이터 파일

emp_no birth_date first_name last_name gender hire_date

… … … … … …

… … … … … …

… … … … … …

… … … … … …

… … … … … …

… … … … … …

Page 53: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

53

MariaDB : 멀티레인지리드(MRR)

Rowid 기준정렬(Rowid-ordered scan) 드리븐테이블을읽을때멀티레인지리드를적용하는방식.

드라이빙테이블에서레코드를읽고, 조인칼럼을이용해서드리븐테이블을읽을때드리븐테이블의인덱스를읽은다음인덱스끝에추가로저장되어있는 Rowid(MyISAM이나 Aria 스토리지엔진경우),

PK(XtraDB나 InnoDB 스토리지엔진경우)를기준으로정렬을수행후,

정렬순서대로읽는방식이다.

Extra 필드에는 “Rowid-ordered scan” 이라는문구가표시된다.

Page 54: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

54

MariaDB : 멀티레인지리드(MRR)

Rowid 기준정렬(Rowid-ordered scan)

set optimizer_switch='mrr=on';

set optimizer_switch='mrr_sort_keys=on';

select * from employees where first_name>='A' and first_name<'B';

43000번 정도의 데이터 파일 랜덤 I/O 발생

Page 55: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

55

MariaDB : 멀티레인지리드(MRR)

Key 기준정렬(Key-ordered scan) Rowid 기준정렬과달리드라이빙테이블을읽은후조인칼럼을정렬해서그순서대로드리븐테이블을읽는방법이다.

드리븐테이블이 XtraDB나 InnoDB 스토리지엔진을사용하는테이블이면서조인조건에사용된칼럼이드리븐테이블의프라이머리키인경우 Key 값기준정렬최적화방법이사용된다.

Extra 필드에는 “Key-ordered scan”이라는문구가표시된다.

Page 56: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

56

MariaDB : 멀티레인지리드(MRR)

Key 기준정렬(Key-ordered scan)

set join_cache_level=8;

set optimizer_switch='mrr=ON';

set optimizer_switch='mrr_sort_keys=ON';

set optimizer_switch='join_cache_hashed=ON';

set optimizer_switch='join_cache_bka=ON';

select * from employees e, salaries s where s.emp_no=e.emp_no;

드라이빙 테이블 (employees)

MRR 버퍼(emp_no 칼럼 정렬)

드리븐 테이블 (salaries)

Page 57: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

57

MariaDB : 멀티레인지리드(MRR)

Key와 Rowid 모두정렬(Key-ordered, Rowid-ordered scan) 멀티레인지리드가배치키액세스조인에사용되면 Key와 Rowid 모두를정렬해서데이터파일랜덤읽기를최소화한다.

Extra 필드에는 “key-ordered Rowid-ordered scan”이라는문구가표시된다.

Page 58: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

58

MariaDB : 멀티레인지리드(MRR)

Key와 Rowid 모두정렬(Key-ordered, Rowid-ordered scan)

set join_cache_level=8;

set optimizer_switch='mrr=ON';

set optimizer_switch='mrr_sort_keys=ON';

select straight_join * from employees e, dept_emp de

where de.emp_no=e.emp_no;

드라이빙 테이블 (employees)

MRR 버퍼

드리븐 테이블 (dept_emp)

멀티 레인지 리드(Key-ordered)

인덱스 (ix_empno_formdate)

MRR 버퍼

멀티 레인지 리드(Rowid-ordered)

Page 59: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

59

MariaDB : 멀티레인지리드(MRR)

멀티레인지리드최적화와정렬 멀티레인지리드최적화의 3가지알고리즘모두기본적으로조인버퍼를사용한다.

블록네스티드루프조인(Block Nested Loop Join, BNL Join)에서도알겠지만, 조인이조인버퍼를이용해서실행되는경우에는기본적으로드라이빙테이블에서레코드를읽은순서가조인최종단계까지유지되지않을수있다.

Page 60: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

60

MariaDB : 멀티레인지리드(MRR)

멀티레인지리드최적화와정렬

set join_cache_level=8;

set optimizer_switch='mrr=ON';

set optimizer_switch='mrr_sort_keys=ON';

set optimizer_switch='join_cache_hashed=ON';

set optimizer_switch='join_cache_bka=ON';

-- // Rowid-ordered scan

select * from employees

where first_name>='A' and first_name<'B'

order by first_name;

-- // Rowid-ordered scan

select * from employees

where first_name>='A' and first_name<'B';

-- // order by first_name;

멀티 레인지 리드 최적화보다는 인덱스 순서대로읽으면서 별도의 정렬을 수행하지 않는 것이 더비용이 적게 든다고 예측

Page 61: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

61

멀티레인지리드최적화와정렬

MariaDB : 멀티레인지리드(MRR)

-- // key-ordered scan

select * from employees e, salaries s

where s.emp_no=e.emp_no and e.emp_no between 10001 and 10020

order by first_name;멀티 레인지 리드 최적화를 적용하는 것이 더효과적 일 것으로 예측

-- // Key-ordered Rowid-ordered scan

select straight_join * from employees e, dept_emp de

where de.emp_no=e.emp_no and e.emp_no between 10001 and 10100

order by e.emp_no;멀티 레인지 리드 최적화를 적용하는 것이 더효과적 일 것으로 예측

Page 62: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

62

MariaDB : 멀티레인지리드(MRR)

멀티레인지리드최적화주의사항 멀티레인지리드알고리즘은읽어들인인덱스튜플에대한정렬작업이우선시되야함으로, 데이터의크기가작아서 XtraDB나 InnoDB 버퍼풀에모두적재될수있는경우라면오히려더많은시스템자원을소비할수있다.

또한 “LIMIT n”이나 “ORDER BY LIMIT n” 형태의쿼리에서 n 값이작은수치라면불필요하게많은인덱스튜플들을읽어서정렬함으로, 성능이오히려떨어질수있다.

정렬메모리공간은 mrr_buffer_size라는시스템변수로크기조정이가능하다.

Page 63: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

63

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 64: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

64

MariaDB : 인덱스머지(Index merge)

인덱스머지(Index merge) 쿼리에서한테이블에대한 WHERE 조건이여러개가있다하더라도하나의인덱스에포함된칼럼에대한조건만으로인덱스를검색하고나머지조건은읽혀진레코드에대해서체크하는형태로만사용하는것이일반적이다.

하지만여러개의 WHERE 조건절이있을때각각의조건들이서로다른인덱스를이용할수밖에없는형태의쿼리이면서도각각의조건을만족하는레코드건수가많을것으로예상될때에 MariaDB는인덱스머지실행계획을선택하게된다.

Page 65: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

65

MariaDB : 인덱스머지(Index merge)

인덱스머지(Index merge)

select *

from employees

where first_name='Matt‘

and hire_date between '1995-01-01' and '2000-01-01‘;

first_name match rows : 233

Hire_date match rows : 34028

set optimizer_switch='index_merge_sort_intersection=on';

select * from employees

where first_name between 'A' and 'B'

and hire_date between '1995-01-01' and '2000-01-01';

Optimization

Page 66: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

66

Using union WHERE 절에사용된 2개이상의조건이각각의인덱스를사용하되, 이조건들이 OR로연결된경우에사용되는알고리즘이다.

MariaDB : 인덱스머지(Index merge)

select * from employees

where first_name=‘Matt’

or hire_date='1987-03-31‘;

Extra 필드에 “Using union(ix_first_name, ix_hiredate”) 표시의의미는 Index_merge 최적화가 ix_firstname

인덱스의검색결과와 ix_hiredate 인덱스검색결과를 “union“ 알고리즘으로병합했다는 의미이다.

여기서병합은두집합의합집합을가져왔다는것을의미한다.

Page 67: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

67

Using union first_name, hire_date 칼럼을검색한결과가프라이머리키로이미각각정렬되어있다.

그래서 MariaDB 서버는두집합에서하나씩가져와서서로비교하면서프라이머리키인 emp_no 칼럼의값이중복된레코드들을정렬없이걸러낼수있다. (우선순위큐)

“Using union”과 “Using sort union” 알고리즘의가장큰차이이다.

MariaDB : 인덱스머지(Index merge)

select * from employees where first_name='Matt';

select * from employees where hire_date='1987-03-31';

Page 68: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

68

MariaDB : 인덱스머지(Index merge)

Using sort_union 인덱스머지(Index merge)의 “Using sort_union” 알고리즘은 “Using sort

union”과거의흡사하게동작한다.

다른점은, 우선순위큐를사용하지못하여 MariaDB 서버는두집합의결과에서중복을제거하기위하여각집합을 emp_no 칼럼으로정렬한다음중복제거를수행한다.

select * from employees

where first_name='Matt'

or hire_date between '1987-03-01’ and '1987-03-31';

hire_date로는 정렬되어 있지만, emp_no 칼럼으로는 정렬되어 있지 않다 (범위 조건)

Page 69: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

69

MariaDB : 인덱스머지(Index merge)

Using intersect 각각의인덱스를사용할수있는 WHERE 조건이 AND 연산자로연결된경우사용할수있는최적화알고리즘이다.

Using union 알고리즘과단하나의차이는중복을제거하고합집합을반환하면 “Using union”이고, 교집합을반환하면 “Using intersect”이다.

select * from employees

where first_name='Matt’

and hire_date='1991-07-22’;

Ix_hiredate와 ix_firstname 두개의인덱스를 이용해서각각의결과집합을 만든후두집합의결과를“Using intersect” 알고리즘을 이용해서교집합의레코드만찾아서리턴했다는 것을의미한다.

Page 70: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

70

MariaDB : 인덱스머지(Index merge)

Using sort_intersect MySQL 5.5 버전이나 5.6 버전에서는 “Using union”이사용될수없는경우에는 “Using sort_union”이있지만, “Using intersect”이사용될수없는경우에는 “Using sort_intersect” 최적화알고리즘이제공되지않는다.

MariaDB 10.0 부터는 “Using sort_intersect” 최적화알고리즘이제공된다.

select *

from employees

where first_name like 'Matt%‘

and hire_date='1991-07-22';

두집합의결과를 employees 테이블의프리미어 키인 emp_no 칼럼으로정렬한다음교집합만필터링해서 사용자에게반환한것이다.

Page 71: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

71

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 72: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

72

MariaDB : 테이블조인

조인의종류 MySQL 5.5 버전과 MariaDB 5.2 버전까지는네스티드루프(Nested

Loop)의조인형태밖에없었지만, 현재는아래와같이다양하다.

INNER JOIN은어느테이블을읽어도결과가달라지지않지만, OUTER

JOIN은반드시 OUTER가되는테이블을먼저읽어야하기때문에조인순서를옵티마이저가선택할수없다.

INNER JOINOUTER

JOIN

LEFT OUTER

JOIN

RIGHT OUTER

JOIN

FULL OUTER

JOIN

NATURAL JOIN

CARTESLAN JOIN

FULL JOINCROSS

JOIN

조인의 종류 조인의 조건에 따라 분류

Page 73: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

73

MariaDB : 테이블조인

Page 74: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

74

MariaDB : 테이블조인

INNER JOIN(SIMPLE JOIN) 일반적인 JOIN은 INNER JOIN을지칭한다.

최종적으로선택될레코드가 INNER 테이블에의해결정되는경우를INNER JOIN이라고한다.

INNER JOIN은조건에만족하는레코드만조인결과로가져옵니다.

SELECT column_name(s)

FROM table1

INNER JOIN table2

ON table1.column_name=table2.column_name;

Page 75: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

75

MariaDB : 테이블조인

OUTER JOIN 조인의결과를결정하는아우터테이블이조인의왼쪽에있는지오른쪽에있는지에따라 LEFT OUTER JOIN과 RIGTH OUTER JOIN, 그리고 FULL

OUTER JOIN으로나뉜다.

INNER TABLE이조인의결과에전혀영향을미치지않고, OUTER

TABLE의내용에따라조인의결과가결정되는것이 OUTER JOIN의특징이다.

Page 76: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

76

MariaDB : 테이블조인

OUTER JOIN(LEFT OUTER JOIN) LEFT OUTER JOIN은왼쪽테이블의모든행을반환하고, 오른쪽테이블에서조인값과일치하는행을반환한다.

일치하는항목이없는경우오른쪽테이블엔 NULL이기록됩니다.

SELECT column_name(s)

FROM table1 (OUTER TABLE)

LEFT OUTER JOIN table2 (INNER TABLE)

ON table1.column_name=table2.column_name;

Page 77: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

77

MariaDB : 테이블조인

OUTER JOIN(RIGHT OUTER JOIN) RIGHT OUTER JOIN은오른쪽테이블의모든행을반환하고, 왼쪽테이블에서조인값과일치하는행을반환한다.

일치하는항목이없는경우왼쪽테이블엔 NULL이기록됩니다.

SELECT column_name(s)

FROM table1 (INNER TABLE)

RIGHT OUTER JOIN table2 (OUTER TABLE)

ON table1.column_name=table2.column_name;

Page 78: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

78

MariaDB : 테이블조인

OUTER JOIN(FULL OUTER JOIN) FULL OUTER JOIN은왼쪽, 오른쪽테이블의모든행을반환하고, 왼쪽테이블에서조인값과일치하는행을반환한다.

SELECT column_name(s)

FROM table1

FULL OUTER JOIN table2

ON table1.column_name=table2.column_name;

Page 79: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

79

MariaDB : 테이블조인

OUTER JOIN 표기주의사항 WHERE 절에명시되는조건은 OUTER JOIN이나 INNER JOIN에관계없이조인된결과에대해모두적용된다.

그래서, OUTER JOIN으로연결되는테이블이있는쿼리에서는가능하다면모든조건을 ON 절에명시한다.

-- // 순수하게 OUTER JOIN 표현한 쿼리select *

from employees e

left outer join salaries s on s.emp_no and s.salary > 5000;

-- // 순수하게 INNER JOIN 으로 표현한 쿼리select *

from employees e

inner join salaries s on s.emp_no

where s.salry > 5000;

Page 80: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

80

MariaDB : 테이블조인

NATURAL JOIN NATURAL JOIN은조건을명시하지않아도된다는편리함이있지만사실각테이블의칼럼이름에의해쿼리가자동으로변경될수있다는문제가있다.

즉, NATURAL JOIN으로조인하는테이블은같은칼럼명을사용할때자동으로조인의조건으로사용돼버릴수있다는점을고려해야한다.

또한애플리케이션이변경되면서테이블구조를변경할때도 NATURAL

JOIN 방식인지확인해야하며, 이런작업들은유지보수비용만높아질수있는역효과가있다.

Page 81: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

81

MariaDB : 테이블조인

NATURAL JOIN

select *

from employees e

natural join salaries s;

이예제는 employees 테이블의 emp_no 칼럼과 salaries 테이블의 emp_no 칼럼을조인하는쿼리다.

현재두테이블에는이름이같은칼럼으로 emp_no만존재하기 때문에결국 “NATURAL JOIN salaries s = INNER JOIN salaries s ON s.emp_no=e.emp_no”

select *

from employees e

inner join salaries s ON s.emp_no=e.emp_no;

현재는동일한쿼리

주의 !! 서로 이름이 같은 칼럼을 모두 조인 조건으로 사용함.

Page 82: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

82

MariaDB : 테이블조인

CARTESLAN JOIN FULL JOIN 또는 CROSS JOIN 이라고도한다.

조건자체가없이 2개테이블의모든레코드조합을결과로가져오는조인방식이다.

레코드건수가많아지면조인의결과건수가기하급수적으로늘어나므로MariaDB 서버자체를응답불능상태에빠질수있다.

SQL 표준에서는 CROSS JOIN을카테시안조인과같은방식으로의미하지만 MariaDB에서 CROSS JOIN을사용하는경우 INNER JOIN과같이 ON 절이나 WHERE 절에조인조건을부여하는것이가능하며,

이렇게작성된 CROSS JOIN은 INNER JOIN과같은방식이다.

Page 83: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

83

MariaDB : 테이블조인

CARTESLAN JOIN MariaDB에서카테시안조인과이너조인은문법적으로구분되지않는다.

조인으로연결되는조건이적절히있다면이너조인으로처리되고, 연결조건이없으면카테시안조인이된다.

그래서 CROSS JOIN이나 INNER JOIN을특별히구분해서사용하지않는다.

select d.*, e.*

from departments d

inner join employees e on d.emp_no=e.emp_no;

select d.*, e.*

from departments d

cross join employees e on d.emp_no=e.emp_no;

Page 84: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

84

MariaDB : 테이블조인

조인알고리즘 MariaDB 5.3 버전까지는네스티드루프(Nested Loop) 알고리즘형태밖에없었지만, 현재는아래와같이다양하다.

• 단순네스티드루프 (Simple Nested Loop)

• 블록네스티드루프 (Block Nested Loop)

• 블록네스티드루프해시 (Block Nested Loop Hash)

• 블록인덱스 (Block Index Join, Batched Key Access)

• 블록인덱스해시 (Block Index Hash Join, Batched Key Access Hash)

Page 85: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

85

MariaDB : 테이블조인

조인캐시레벨(join_cache_level) MariaDB 10.0에서는 4가지형태의블록기반조인알고리즘을제공하고있는데, 이들은모두조인버퍼에예전방식으로레코드필드를복사하는플랫(flat)방식과포인터만조인버퍼에저장하는인크리멘탈(Incremental)

방식으로활용될수있다.

전체블록기반의조인은다음과같이 8가지처리알고리즘으로구분된다.• 블록네스티드루프 (Block Nested Loop - Flat)

• 블록네스티드루프 (Block Nested Loop - Incremental)

• 블록네스티드루프 (Block Nested Loop Hash - Flat)

• 블록네스티드루프 (Block Nested Loop Hash - Incremental)

• 배치키액세스(Batched Key Access – Flat)

• 배치키액세스(Batched Key Access – Incremental)

• 배치키액세스(Batched Key Access Hash – Flat)

• 배치키액세스(Batched Key Access Hash – Incremental)

Page 86: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

86

MariaDB : 테이블조인

조인캐시레벨(join_cache_level) 앞의 8가지알고리즘중에서어떤알고리즘을사용할지를결정하는데는

3개의 optimizer_switch 옵션(join_cache_incremental, join_cache_hashed,

join_cache_bka)과 join_cache_level이라는 시스템설정변수가사용된다.

옵티마이저가선택할수있는조인최적화방법을결정하는데optimizer_switch 옵션만영향을미치는것이아니라, join_cache_level

시스템설정또한영향을미치게된다.

앞의 1~8까지의조인알고리즘은 cache_level 설정정수값보다작은경우에만해당조인알고리즘을사용할수있다.

즉 cache_level(default :1) 이 1이면 “Nested Loop”와 “flat Block Nested Loop” 조인만사용가능하고,

cache_level 값이 8이면앞의모든알고리즘을사용가능해진다.

각 optimizer_switch 옵션의 ON, OFF 여부에 따라 해당 알고리즘의 사용 여부가 판단됨.

Page 87: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

87

MariaDB : 테이블조인

조인버퍼설정 블록기반조인(조인버퍼를사용하는조인)알고리즘에서사용할수있는메모리상의조인버퍼최대크기는 join_buffer_size 시스템설정에의해서결정된다.

최소한조인대상레코드한건은저장될수있어야하며, MariaDB

5.3부터는 join_cache_space_limit 시스템설정변수로최대할당가능한조인버퍼사이즈를제한한다.

set optimizer_switch='optimize_join_buffer_size=ON';

set join_cache_space_limit=5*1024*1024;

쿼리의실행계획에서 수립된예상레코드건수에맞게 join_cache_space_limit 시스템설정의한도내에서적절히필요한만큼의메모리공간을할당하게된다.

Page 88: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

88

MariaDB : 테이블조인

단순네스티드루프(Simple Nested Loop, NL) 단순네스티드루프조인에서는절대조인버퍼(join_buffer_size)를사용하지않는다.

인덱스를적절히이용해서조인을수행하는쿼리에서는단순네스티드알고리즘의조인이사용된다. 일반적으로웹서비스용 OLTP 쿼리에서는인덱스를적절히이용해서조인되므로대부분의쿼리들이단순네스티드루프조인으로처리될것이다.

MariaDB의네스티드-루프조인은 “Single-sweep mult join”이라고표현하기도한다. 의미는조인에참여하는테이블의개수만큼반복루프가중첩되는것을말한다.

Page 89: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

89

MariaDB : 테이블조인

단순네스티드루프(Simple Nested Loop, NL)

select d.dept_name, e.first_name

from departments d, employees e, dept_emp de

where de.dept_no=d.dept_no

and e.emp_no=de.emp_no;

FOR ( record1 IN departments ) {

FOR ( record2 IN dept_emp && record2.dept_no = record1.dept_no) {

FOR ( record3 IN employees && record3.emp_no = record2.emp_no) {

RETURN (record1.dept_name, record3.first_name)

}

}

}

의사 코드로 변경

3번중첩되긴했지만, 전체적으로 반복루프는 1개다.

즉, 반복루프를돌면서레코드단위로모든조인대상테이블을차례대로 읽는방식을 “Single-sweep multi join”이라고한다.

조인에서드리븐테이블들은 단순히드라이빙테이블의레코드를읽는순서대로검색(Lookup)만한다.

Page 90: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

90

MariaDB : 테이블조인

블록네스티드루프(Block Nested Loop, BNL) 블록네스티드조인과가장큰차이는조인버퍼의사용여부와조인에서드라이빙테이블과드리븐테이블이어떤순서로조인되는지이다.

조인알고리즘에서 “Block”가들어가면별도의버퍼가사용되었다는걸의미한다. 블록네스티드루프조인도마찬가지로조인버퍼를사용한다.

어떤방식으로도드리븐테이블의풀테이블스캔이나인덱스풀스캔을피할수없다면옵티마이저는드라이빙테이블에서읽은레코드를메모리에캐시한후드리븐테이블과이메모리캐시를조인하는형태로처리한다. 이때사용되는메모리의캐시를조인버퍼라한다.

일반적으로조인이수행된후가져오는결과는드라이빙테이블의순서에의해결정되지만조인버퍼가사용되는조인에서는결과의정렬순서가흐트러질수있다.

Page 91: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

91

MariaDB : 테이블조인

블록네스티드루프(Block Nested Loop, BNL)

Page 92: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

92

MariaDB : 테이블조인

블록네스티드루프(Block Nested Loop, BNL)

select *

from dept_emp de, employees e

where de.from_date > '2000-01-01' and e.emp_no < 109004;

각테이블에대한조건은 WHERE 절에있지만두테이블을연결고리역할을하는조인조건은없다.

그래서 dept_emp 테이블에서 from_date > ‘2000-01-01’인레코드(10,616건)와 employees 테이블에서 emp_no < 109004

조건을만족하는레코드(99,003건)을카테시안조인을수행한다. (총 10,616 번반복수행)

하지만조인버퍼를사용하면, 실제드라이빙테이블의 결과는조인버퍼에담아두고, 드리븐테이블을 먼저읽고조인버퍼에서일치하는레코드를찾는방식으로 처리된다.

Page 93: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

93

MariaDB : 테이블조인

블록네스티드루프해시(Block Nested Loop Hash, BNLH) MariaDB의해시조인은해시알고리즘을이용하며, 동등조건에서만사용가능하다.

해시조인은크게빌드단계(Build phase)와프로브단계(Probe phase)로실행된다. 빌드단계에서는레코드건수가적은테이블을일반적으로사용하는데, 선택된테이블의레코드를읽어서조인칼럼의해시값을계산하여그값으로해시테이블을생성한다.

프로브단계에서는남은테이블을스캔하고각로우마다조인칼럼의해시를계산해서빌드단계에서만들어진해시테이블을검색하여최종조인결과를만든다.

조인칼럼값의길이에관계없이조인칼럼의해시값으로검색하기때문에네스티드루프조인보다매우빠르다.

Page 94: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

94

MariaDB : 테이블조인

블록네스티드루프해시(Block Nested Loop Hash, BNLH)

Page 95: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

95

MariaDB : 테이블조인

블록네스티드루프해시(Block Nested Loop Hash, BNLH)

set optimizer_switch='join_cache_incremental=on';

set optimizer_switch='join_cache_hashed=on';

set optimizer_switch='mrr=on';

set optimizer_switch='mrr_sort_keys=on';

set join_cache_level=8;

select * from dept_emp de, departments d where d.dept_no=de.dept_no;

Page 96: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

96

MariaDB : 테이블조인

블록인덱스조인(Block Index Join, Batched Key Access, BKA) 블록인덱스조인은배치키액세스(Batched Key Access, BKA)

조인이라고도하는데, 배치키액세스조인은내부적으로멀티레인지리드(Multi Range Read, MRR) 최적화기능을사용하여조인을수행한다.

우선드라이빙테이블을읽어서필요한칼럼과조인칼럼을조인버퍼에저장한다. 조인버퍼의내용이가득채워지면조인버퍼의내용을멀티레인지리드(MRR) 엔진으로전송하는데, 멀티레인지리드(MRR) 엔진은넘겨받은버퍼의내용을적절한방식(Rowid, Key, Rowid 와 Key)으로정렬한다음드리븐테이블을읽어서리턴한다.

Page 97: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

97

MariaDB : 테이블조인

블록인덱스조인(Block Index Join, Batched Key Access, BKA)

Page 98: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

98

MariaDB : 테이블조인

블록인덱스해시조인(Block Index Hash Join, Batched Key

Access Hash) 블록인덱스해시조인은배치키인덱스(Batched Key Access, BKA) 해시조인이라고도하는데, 조인알고리즘의이름그대로배치키액세스로테이블을읽어서해시조인을수행하는것을의미한다.

• 드라이빙테이블을멀티레인지리드접근방법으로조회해서해시테이블을생성(빌드 단계)

• 드리븐테이블을읽어서해시테이블을검색(프로브 단계)해서결과반환

Page 99: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

99

MariaDB : 테이블조인

MariaDB 5.3 버전이후효율성증대 MariaDB 5.3 버전부터는조인버퍼를조금더효율적으로사용할수있도록조인버퍼에저장하는레코드포맷이변경되었다.

새로운포맷은다음과같은효율성을제공한다.• 가변길이칼럼과 NULL 값을좀더공간효율적으로기록• 조인버퍼의증분(Incremental) 모드지원• 아우터조인과세미조인을위한알고리즘사용

Page 100: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

100

MariaDB : 테이블조인

Incremental Join Buffer MariaDB 5.3 버전부터는 3개이상의테이블이조인될때조인버퍼에중복된내용을제거하고중복되지않는내용만저장할수있도록개선된Incremental Join 기법을제공한다.

첫번째조인버퍼(테이블 A와테이블 B사이의조인버퍼)는테이블 A의레코드값을임시로저장하고테이블 B와비교하기위한용도로사용한다.

두번째조인버퍼(“테이블 A와테이블 B 결과”와테이블 C 사이의조인버퍼)는앞선결과값과테이블 C 조인을위해임시로데이터를저장하는용도로사용한다.

Page 101: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

101

MariaDB : 테이블조인

Incremental Join Buffer 테이블 A와 테이블 B 결과가 저장된 임시 공간에 접근할 수 있는 “포인터“ 값만 저장

Page 102: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

102

MariaDB : 테이블조인

Join Buffer with Outer-Join/Semi-Join MariaDB 5.3부터는아우터조인(OUTER JOIN)이나세미조인(SEMI-

JOIN)에서도조인버퍼를사용할수있게되었다.

OUTER JOIN 에서는조인버퍼내부에 “매칭플래그”, 즉테이블 A가기준테이블인경우관련데이터와매칭되는여부를체크하는플래그를내부적으로포함한다. (Default OFF)

조인버퍼에서테이블과테이블 B간데이터매칭여부수행이후여전히OFF 값을플래그로가진필드의경우, 테이블 B에해당하는컬럼을NULL로채운다.

SEMI JOIN(IN 안의서브쿼리같은조건)에서도매칭플래그가비슷하게사용된다. 다만매칭플래그가 ON이되는시점에서관련데이터를테이블B에에서더이상탐색하지않는차이가있다.

Page 103: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

103

MariaDB : 테이블조인

Join Buffer with Outer-Join/Semi-Join 플래그 값 (ON/OFF)에 따라 구분된다.

Page 104: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

104

MariaDB : 테이블조인

조인의주의사항(조인실행결과의정렬순서)

select de.dept_no, e.emp_no, e.first_name

from dept_emp de, employees e

where e.emp_no=de.emp_no

and de.dept_no='d005';

이쿼리는 WHERE 조건에 dept_no=‘d005’로고정돼있으므로 emp_no로정렬되었다.

결국이쿼리는 “ORDER BY de.emp_no ASC”를명시하진않았지만같은효과이다.

하지만, 레코드건수가다르거나인덱스사용여부가달라옵티마이저가 다른판단을하면결과값은다르다.

그러므로 SQL 쿼리에서결과의정렬을보장하는방법은 ORDER BY 절을사용하는것밖에없다.

Page 105: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

105

MariaDB : 테이블조인

조인의주의사항(INNER JOIN과 OUTER JOIN의선택) INNER JOIN은양쪽테이블모두레코드가존재하는경우에만반환하고,

OUTER JOIN은아우터테이블에존재하면레코드를반환한다.

OUTER JOIN을사용하지않아도될것을 OUTER JOIN을사용하는경우,

OUTER JOIN으로실행하면쿼리의처리가느려진다고생각하여 INNER

JOIN으로억지로변경하는경우 INNER JOIN과 OUTER JOIN은성능을고려해서선택할것이아니라업무요건에따라선택하는것이바람직하다.

Page 106: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

106

Agenda

• 풀테이블스캔

• ORDER BY 처리(Using filesort)

• GROUP BY 처리

• DISTINCT 처리

• 임시테이블(Using Temporary)

• 인덱스컨디션푸시다운(Index Condition Pushdown, ICP)

• 멀티레인지리드(Multi Range Read)

• 인덱스머지(Index merge)

• 테이블조인

• 서브쿼리

Page 107: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

107

MariaDB : 서브쿼리

서브쿼리 MySQL 서버는 IN(subquery)와 같은세미조인형태로사용된서브쿼리에대한최적화방법이 EXISTS로풀어서실행하는것하나밖에없었다.

상관서브쿼리(Correlated subquery)이든지아니든지(Non-conrrelated

subquery) 무조건이방법으로처리했다.

MariaDB 5.3부터는서브쿼리의최적화가개선되었다.

세미조인서브쿼리최적화

Table pullout FirstMatchSemi-join

MaterializationLooseScan

Duplicate Weedout

세미조인이아닌서브쿼리최적화

Materialization IN-to-EXISTS

서브 쿼리의 최적화 종류

Page 108: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

108

MariaDB : 서브쿼리

세미조인서브쿼리최적화 MariaDB 5.3부터는 IN절을 EXISTS절로수동으로바꾸지않아도,

자동으로옵티마이저가알아서처리해준다.

MariaDB 10.0 버전에서는세미조인형태의서브쿼리과다음과같이5가지형태로최적화된다.

• Table pullout 최적화• FirstMatch 최적화• Semi-join Materialization 최적화• LooseScan 최적화• Duplicate Weedout 최적화

Page 109: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

109

MariaDB : 서브쿼리

Table pullout 최적화 세미조인의서브쿼리에사용된테이블을아우터쿼리로끄집어낸후에쿼리를조인쿼리로재작성하는형태의최적화이다.

서브쿼리최적화가도입되기이전에수동으로쿼리를튜닝하던대표적인방법이다.

select * from employees e

where e.emp_no in (select de.emp_no from dept_emp de where de.dept_no='d009');

id 칼럼의값이다르지않다는것은, 두쿼리가서브쿼리의형태가아니라조인으로실행되었음을 의미한다.

이쿼리의실행계획은 dept_emp 테이블을 인덱스레인지스캔으로 43004건을읽고그횟수만큼 employees 테이블을 조회했다.

단순히쿼리수행을위해서읽은레코드건수만해도 1/10으로작업량이 줄어들었다.

employees : 300252 rows

Page 110: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

110

MariaDB : 서브쿼리

FirstMatch 최적화 이는 IN(subquery) 형태의세미조인을 EXISTS(subquery) 형태로튜닝한것과비슷한방법으로실행된다.

FirstMatch 최적화는 optimizer_switc의 semijoin 옵션과 firstmatch 옵션이ON으로활성화된경우에만사용할수있다. MariaDB 10.0 이후버전에서는기본적으로이두옵션은 ON으로활성화되어있다.

만약 firstmatch 최적화만비활성화하려면 semijoin 옵티마이저옵션은ON으로활성화하되, firstmatch 옵티마이저옵션만 OFF로비활성화하면된다.

일반적으로 MariaDB의 FirstMatch 최적화는아우터쿼리가독립적으로인덱스를적절히사용할수있는별도의조건을가지고있으면서서브쿼리가사용된경우에자주선택된다.

Page 111: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

111

MariaDB : 서브쿼리

FirstMatch 최적화

select *

from employees e where e.first_name='Matt'

and e.emp_no IN (

select t.emp_no from titles t

where t.from_date between '1995-01-01' and '1995-01-30'

);

“FirstMatch(e)” 문구는 employees 테이블의레코드에대해서 titles 테이블에일치하는레코드가1건만찾으면더이상의 titles 테이블을 검색하지않는다는것을의미한다.

실제의미론적으로는 EXISTS(subquery)와동일하게처리된것이다.

하지만, FirstMatch는서브쿼리가아니라조인으로풀어서실행하면서 일치하는첫번째레코드만검색한다.

Page 112: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

112

MariaDB : 서브쿼리

FirstMatch 최적화

select * from Country

where Country.code IN (select City.Country

from City

where City.Population > 1*1000*1000)

and Country.continent='Europe'

Page 113: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

113

MariaDB : 서브쿼리

Semi-join Materialization 최적화 이는세미조인에사용된서브쿼리를통째로구체화를시켜서쿼리를최적화한다는의미이다.(내부임시테이블을생성한다는것)

“MATERIALIZED” 최적화에는 “Materialization – Scan”과 “Materialization

– Lookup” 2가지전략이있는데, 구체화된임시테이블이조인에서드리븐테이블로사용되면 “Materialization – Lookup” 이라하고, 인덱스를만들고난이후에는구체화된임시테이블이드라이빙테이블로사용되면서풀테이블스캔으로사용되었는데, 이를 “Materialization – Scan” 이라고한다.

다른서브쿼리최적화와달리 GROUP BY 절이있어도최적화전략은사용된다.

Page 114: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

114

MariaDB : 서브쿼리

Semi-join Materialization 최적화 Semi-join Materialization 최적화는 optimizer_switch의 semijoin 옵션과

materialization 옵션이 ON으로활성화된경우에만사용된다.

세미조인이아닌서브쿼리의최적화에도구체화를이용한최적화가사용될수있다. 만약 materialization 옵티마이저스위치가 OFF로비활성화된다면세미조인이아닌서브쿼리최적화에도구체화를이용한최적화는사용되지못하게된다.

Page 115: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

115

MariaDB : 서브쿼리

Semi-join Materialization 최적화

select *

from employees e where e.emp_no in (

select t.emp_no from titles t

where t.from_date between '1995-01-01' and '1995-01-30'

);

IN(subquery) 형태의 쿼리에서 서브 쿼리는 반드시 유니크한 값만을 리턴해야 한다.

alter table titles add index ix_formdate(from_date);

Materialization

- Lookup

Materialization

- Scan

Page 116: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

116

MariaDB : 서브쿼리

Semi-join Materialization 최적화

select * from Country

where Country.code IN (select City.Country

from City

where City.Population > 7*1000*1000)

and Country.continent='Europe'

Page 117: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

117

MariaDB : 서브쿼리

LooseScan 최적화 LooseScan 최적화는루스인덱스스캔으로서브쿼리테이블을읽고, 그다음으로아우터테이블을드리븐으로조인을수행한다. 그래서서브쿼리부분이 Loose Index Scan을사용할수있는조건이갖춰져야사용할수있는최적화이다.

옵티마이저가 LooseScan 최적화를사용하지못하도록비활성화하려면loosescan 옵티마이저스위치를 OFF로설정하면된다.

Page 118: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

118

MariaDB : 서브쿼리

LooseScan 최적화

set optimizer_switch='materialization=off';

set optimizer_switch='firstmatch=off';

select * from departments d where d.dept_no in (

select de.dept_no from dept_emp de

);

dept_emp 테이블의프라이머리키를루스인덱스스캔으로유니크한 dept_no만읽는다면아주효율적으로서브쿼리부분을실행할수있다.

서브쿼리에 사용되었던 dept_emp 테이블이드라이빙테이블로 실행되며,

dept_emp 테이블의프라이머리키를 dept_no 부분에서유니크하게 한건씩만읽고있다는것을보여준다.

id 필드의값이동일하게 1이라는것도 MariaDB 내부적으로는 조인처럼 처리되었다는것을말해준다.

dept_emp : 331603 row departments : 9 row

dept_emp pk : dept_no + emp_no

Page 119: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

119

MariaDB : 서브쿼리

LooseScan 최적화

select * from Country

where Country.code in (select country_code from Satellite)

Page 120: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

120

MariaDB : 서브쿼리

Duplicate Weedout 최적화• Duplicate Weedout은세미조인서브쿼리를일반적으로 INNER JOIN 쿼리로바꿔서실행하고마지막에중복된레코드를제거하는방법으로처리되는최적화알고리즘이다.

• 우선중복된레코드에대한고려없이조인을해서중복된레코드까지포함한모집합을만들고, 그이후에중복된레코드만잡초를뽑듯이제거한다.

• 실행계획에서는 “Duplicate Weedout”이라는문구가별도로표시되지않지만,

Extra 필드에 “Start temporary”와 “End temporar” 문구가별도로표시된다.

Page 121: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

121

Duplicate Weedout 최적화

MariaDB : 서브쿼리

select * from employees e

where e.emp_no in (select s.emp_no from salaries s where s.salary > 150000);

select e.* from employees e, salaries s

where e.emp_no=s.emp_no and s.salary>150000

group by e.emp_no;

salaries 테이블의 프라이머리 키가(emp_no + from date)이므로salary가 15000 이상인 레코드를 salaries 테이블에서 조회화면 중복된 emp_no 발생 가능

실제로 Duplicate Weedout 최적화알고리즘은원본쿼리를위와같이 INNER JOIN + GROUP BY 절로바꿔서실행하는것과동일한작업으로쿼리를처리한다.

1. salaries 테이블의 ix_salary 인덱스를스캔해서 salary가 150000보다큰사원검색하여 emplyoees 테이블조인실행2. 조인된결과를임시테이블에 저장3. 임시테이블에저장된결과에서 emp_no 기준으로중복제거4. 중복을제거하고남은레코드를최종적으로 반환

Page 122: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

122

Duplicate Weedout 최적화

MariaDB : 서브쿼리

select *

from Country

where Country.code IN (select City.Country

from City

where City.Population > 0.33 * Country.Population

and City.Population > 1*1000*1000);

Page 123: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

123

MariaDB : 서브쿼리

세미조인이아닌서브쿼리최적화 세미조인이아닌서브쿼리형태를사용하는경우에는선택할수있는최적화옵션이별도없다.

이런경우에는서브쿼리를임시테이블로구체화하는 Materialization

최적화나 IN-to-EXISTS 최적화만사용할수있다.• IN (subquery)와 OR연산자로 다른조건이결합된형태• NOT IN (subquery) 형태• SELECT 절에포함된서브쿼리• HAVING 절에포함된서브쿼리• 서브쿼리에 UNION이사용된경우

Page 124: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

124

MariaDB : 서브쿼리

Materialization 쿼리에사용된서브쿼리부분이상관서브쿼리가아닌경우에만사용될수있으며, 세미조인서브쿼리의 Materialization과같이임시테이블로구체화되기때문에내부테이블사이즈가 tmp_table_size와max_heap_table_size 시스템설정에영향을받는다.

Materialization 최적화가사용되는경우 MariaDB 옵티마이저는 NULL을효율적으로처리하기위해아래와같이 2가지부분일치알고리즘을사용한다.

• Rowid-marge partial matching (구체화로 생성되는내부임시테이블의특정칼럼에특수한인덱스를생성, 각각의인덱스스캔하여집합연산과같이병합)

• Table scan partial matching (테이블의 레코드수가적어 Rowid-merge

알고리즘이오버헤드라생각될경우, 버퍼가필요하지않다.)

Rowid-merge partial matching 최적화는내부적으로메모리버퍼를사용하는데, 그메모리버퍼최대공간은 rowid_merge_buff_size 시스템설정변수로제한가능하다.

Page 125: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

125

MariaDB : 서브쿼리

IN-to-EXISTS 세미조인이아닌서브쿼리의최적화에서서브쿼리부분이상관서브쿼리가아닌경우에만 Materialization 최적화를사용할수있다.

만약서브쿼리가외부쿼리의칼럼을참조하는상관서브쿼리에서는 IN-

to-EXISTS 최적화만사용될수있다. IN-to-EXISTS 최적화는말그대로 IN(subquery)를 EXISTS로변환해서실행하는방법이다.

Page 126: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

126

MariaDB : 서브쿼리

IN-to-EXISTS

select * from employees e

where e.emp_no in (select de.emp_no from dept_emp de where de.dept_no='d009')

or e.first_name='Matt';

show warnings;

select `employees`.`e`.`emp_no` AS `emp_no`,

`employees`.`e`.`birth_date` AS `birth_date`,

(생략)

where (<expr_cache><`employees`.`e`.`emp_no`>(<in_optimizer>(`employees`.`e`.`emp_no`,

<exists>

(select `employees`.`de`.`emp_no` from `employees`.`dept_emp` `de`

(생략)

내부적으로 “<EXISTS>”처리가사용된것을확인할수있다.

Page 127: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

127

MariaDB : 서브쿼리

서브쿼리캐시 서브쿼리캐시최적화는상관서브쿼리가아우터쿼리의실행결과레코드건수만큼반복실행되어야할때사용되는최적화알고리즘이다.

서브쿼리캐시는항상내부임시테이블에파라미터값과서브쿼리의결과가함께저장된다. 그리고내부임시테이블에서모든파라미터가저장된칼럼들을묶어서유니크인덱스를생성한다.

서브쿼리캐시가저장되는내부임시테이블은처음에는메모리테이블(힙테이블)로 생성되지만 tmp_table_size나 max_heap_table_size 설정값보다커지면캐시히트율을계산해서캐시를어떻게유지할지를결정한다.

• 캐시의히트율이낮을경우 (HitRatio < 0.2) 서브쿼리캐시는자동적으로비활성화된다.

• 캐시의히트율이적정수준인경우 (0.2 <= HitRatio < 0.7) 지금까지내부임시테이블에캐시된결과는모두삭제하고다시캐싱한다.

• 캐시의히트율이높은경우 (HitRatio >= 0.7) 캐시된메모리기반내부임시테이블을디스크기반으로변환하고계속캐싱한다.

Page 128: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

128

MariaDB : 서브쿼리

서브쿼리캐시

select * from employees e

where e.emp_no in (select de.emp_no from dept_emp de where de.dept_no='d009')

or e.first_name='Matt';

show warnings;

select `employees`.`e`.`emp_no` AS `emp_no`,

`employees`.`e`.`birth_date` AS `birth_date`,

(생략)

where (<expr_cache><`employees`.`e`.`emp_no`>(<in_optimizer>(`employees`.`e`.`emp_no`,

<exists>

(select `employees`.`de`.`emp_no` from `employees`.`dept_emp` `de`

(생략)

여기에서 employees 테이블의레코드를 한건읽을때마다 EXISTS의서브쿼리가매번실행되었다.

이때서브쿼리를서브쿼리의실행결과를별도의메모리에캐싱하여 매번다시실행하지않고,

즉시내용을리턴하는 형태로처리되었다.

파라미터

캐시 결과

Page 129: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

129

Reference

Site : MariaDB Knowledge Base(Server Status Variables)

MariaDB Knowledge Base(Multi Range Read optimization)

MariaDB Knowledge Base(Optimization Strategies)

http://www.rcy.co.kr/xeb/index.php

(MySQL 5.6 신기능 - Multi Range Read (MRR) & Batched Key Access (BKA))

http://gywn.net/2012/07/improve-mariadb-mysql/

Book : “Real MariaDB”

Page 130: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

130

Q & A

Page 131: MariaDB Optimization

Copyright(c)2014 by ora-sysdba. All Page content is property of dbjongjin.lee

Blog : http://ora-sysdba.tistory.com/

131