언제 사용하는가?
옵티마이저가 우리가 사용하는 서비스의 비즈니스를 잘 이해하지 못하고 실행 계획을 수립할 때 사용
MySQL 5.6이전에는 Index Hint를 사용, 이후부터는 Optimizer Hint 사용
Index Hint는 SQL 문법에 맞게 사용해야해서 ANSI-SQL 표준 문법을 준수하지 못하나
Optiomizer Hint는 ANSI-SQL을 준수하는 다른 RDBMS처럼 주석으로 사용
MySQL에서 사용 가능한 힌트
Join 순서를 명시해도 옵티마이저에 의해 join 순서가 변경이 됩니다.
드라이빙, 드리븐 테이블을 예상할 수 없으며 통계정보와 쿼리 조건을 기반으로 분석한 옵티마이저의 최적화 결과가 매우 좋지 않다면 사용합니다.
SELECT, UPDATE, DELETE
쿼리에서 여러 개의 테이블이 조인되는 경우 순서를 고정합니다.
STRAIGHT_JOIN을 언제 사용할까?
임시 테이블과 일반 테이블 조인
임시 테이블끼리 조인(서브쿼리로 파생된 테이블)
일반 테이블끼리 조인
읽어야 할 레코드가 작은 것은
🙆♂️모든 조건에 부합하는 레코드를 의미
❌조건이 없는 모든 레코드를 의미하는 것이 아님
Join에 왜 임시 테이블을 생성하지?
자문자답 - on절의 컬럼에 인덱스가 없는 경우 생성할 것 같다.
💬 왜? 학습 필요
조인의 순서 다음으로 많이 사용하는 힌트이며
대체로 MySQL 옵티마이저는 인덱스 선택을 잘 하는편이지만 3~4개 이상의 컬럼을 포함하는 비슷 한 인덱스가 여러 개 존재하는 경우 실수를 합니다.
사용 예제
SELECT * FROM employees FORCE INDEX(primary) WHERE emp.no = 10001;
USE INDEX
FORCE INDEX
IGNORE INDEX
위의 힌트를
FOR JOIN
,FOR INDEX FOR ORDER BY
,USE INDEX FOR GROUP BY
를 사용하여 용도를 지정할 수 있음
하지만 용도는 옵티마이저가 대부분 최적으로 선택
특징
IGORE INDEX(primary)
같은 힌트도 과거 5버전에서는 먹혔습니다.페이징 쿼리에서 사용되는 기능
SQL_CALC_FOUND_ROWS
를 사용하는 경우 LIMIT
조건에 부합하는 만큼 찾더라도 멈추지 않고 끝까지 검색을 수행FOUND_ROWS()
를 사용하는 경우 SQL_CALC_FOUND_ROWS
가 사용된 쿼리의 LIMIT을 제외한 조건을 만족하는 레코드의 수를 찾음일반적인 경우
SQL_CACL_FOUND_ROWS
보다는 일반 페이징 쿼리가 빠르다. 왜?
일단 SQL_CALC_FOUND_ROWS
는 LIMIT이상의 조건에 부합하는 모든 레코드를 읽어야 함.
실제 조회 데이터를 위해 조건에 부합하는 레코드가 100개라면 100번 랜덤 I/O가 일어남
100개의 레코드에서 실제 조회 데이터를 위해 조건에 부합하는 10개만 보여준다면 10번의 랜덤I/O가 생김
count 쿼리는 둘 다 커버링 인덱스를 활용할 것으로 예상
페이징 쿼리
에서 특정 조건에 부합하는 레코드(Index가 걸린!)의 총 개수를 읽는 경우 Secondary Index Table의 개수만으로 결과를 만들어짐 (커버링 인덱스 활용), 실제 레코드를 찾는 랜덤I/O가 발생 X
종류
인덱스, 테이블, 쿼리 블록. 글로벌
예시
SELECT /*+ JOIN_ORDER(e, s@subq1) */
COUNT(*)
FROM employees e
WHERE e.first_name='Matt'
AND e.emp_no IN (SELECT / *+ QB_NAME(subq1) */ s.emp_no
FROM salaries s
WHERE s.salary BETWEEN 50000 AND 50500);
사용한 옵티마이저 힌트
1. /+ JOIN_ORDER(e, s@subq1) /
2. /+ QB_NAME(subq1) /
QB_NAME
은 쿼리 블록의 이름 설정을 위한 힌트이며 쿼리블록의 영향범위를 가집니다.
JOIN_ORDER
는 힌트에 명시된 테이블 순서대로 조인을 실행하며 QB_NAME과 동일한 영향범위를 가집니다.
join_buffer_size
같은 경우 값을 변경하면 조인 버퍼를 활용하는 실행 계획을 선택할 수도 있음IN-to-EXISTS
, Meterialization
2가지 방법이 존재
BNL
, NO_BNL
힌트를 사용하면 해시 조인 알고리즘을 유도HASHJOIN
, NO_HASHJOIN
힌트는 8.0.18버전에서만 유효해시 조인 알고리즘을 사용하려면 조인 조건에 인덱스를 사용하지 못하게 해야 함
STRAIGHT_JOIN
을 사용했으나 조인 순서에 맞게 테이블의 순서를 변경해야하는 단점이 존재, 일부만 강제시키고 나머지는 옵티마이저에게 순서를 맞기는 방식이 불가능 하다.STRAIGHT_JOIN
의 단점을 보강하기 위해 나온 힌트JOIN_FIXED_ORDER
: STRAIGHT_JOIN과 동일하게 FRO절 테이블 순서대로 조인을 실행
JOIN_ORDER
: FROM절에 사용된 테이블의 순서가 아니라 힌트에 명시된 테이블 순서대로 실행
JOIN_PREFIX
: 조인에서 드라이빙 테이블만 강제
JOIN_SUFFIX
: 조인에서 가장 마지막 드리븐 테이블만 강제
NO_ICP
는 성능 향상에 도움이 되므로 옵티마이저는 최대한 사용하는 방향으로 계획을 수립, 그래서 ICP
힌트는 제공되지 않음ICP
로 인해 결과적으로 잘못된 실행 계획을 수립할 수도 있음USE INDEX -> 해당 인덱스를 사용
처럼 이름에서 직관적으로 유추할 수 있음USE INDEX
, USE INDEX FOR GROUP BY
, USE INDEX FOR ORDER BY
, IGNORE INDEX
, IGNORE INDEX FOR GROUP BY
.. 존재