- 공통적으로 사용하는 필수 조건절 컬름을 우선한다.
- '=' 조건의 컬럼을 다른 연사자 컬럼보다 우선한다.
- 대분류 중분류 소분류 컬럼순으로 구성한다.
- 위치(조건) 정보 컬럼은 순서(정렬) 정보 컬럼보다 우선한다.
- 조회 건수가 테이블 전체 건수의 1% 미만일때 사용한다.
SELECT A.컬럼들, B.컬럼들, C.컬럼들 FROM 고객 A, 주문 B, 상품 C WHERE A.고객번호 = B.고객번호 AND B.상품번호 = C.상품번호 AND A.고객명 = ? AND B.주문일자 = ? AND C.상품분류 = ?
- 조인절의 우측편 컬럼에 인덱스가 생성돼야한다.
- 첫 번째 조건절 컬럼에 인덱스가 생성되어야한다.
SELECT c.id, c.content, b.title, u.name FROM comments c JOIN books b ON c.book_id = b.id -- books.id (우측 컬럼) 인덱스 필요 JOIN users u ON c.user_id = u.id -- users.id (우측 컬럼) 인덱스 필요 WHERE c.book_id = 123; -- 첫 번째 조건절 컬럼 book_id 인덱스 필요
COST : MySQL이 해당 쿼리를 실행하는 데 걸리는 예상 비용 (비교적 상대적인 값)
Card(Cardinality) : 해당 칼럼에서 예상되는 고유 값의 개수(중복 제거한 값 개수)
Bytes : MySQL이 해당 연산을 수행하는 동안 읽어야 하는 데이터의 크기 (바이트 단위)
- ORDERED
MySQL은 기본적으로 최적의 조인 순서를 선택하려고 하지만, ORDERED 힌트를 사용하면 쿼리가 지정한 순서대로 테이블을 조인하게 강제할 수 있다.SELECT /*+ ORDERED */ * FROM orders, customers WHERE orders.customer_id = customers.customer_id;
- LEADING
쿼리에서 조인 순서를 강제할 수 있으며, ORDERED와 유사하지만 첫 번째 테이블만 명시적으로 지정하는 점에서 다르다.SELECT /*+ LEADING(orders) */ * FROM orders, customers WHERE orders.customer_id = customers.customer_id;3.USE_NL (Nested Loop Join 사용)
보통 중첩 루프 조인은 작은 테이블 간의 조인에 유리하지만, 큰 테이블 간에서는 성능 저하를 초래할 수 있다.SELECT /*+ USE_NL(orders customers) */ * FROM orders, customers WHERE orders.customer_id = customers.customer_id;4.USE_HASH (해시 조인 사용)
해시 조인은 큰 데이터셋을 조인할 때 효율적일 수 있으며, 특히 인덱스를 사용할 수 없을 때 유리하다.SELECT /*+ USE_HASH(orders customers) */ * FROM orders, customers WHERE orders.customer_id = customers.customer_id;5.INDEX (인덱스 사용)
보통 옵티마이저가 선택한 인덱스가 최적이지만, 경우에 따라 직접 인덱스를 지정해줄 필요가 있을 수 있다.SELECT /*+ INDEX(orders idx_customer_id) */ * FROM orders WHERE customer_id = 1001;6.FULL (전체 테이블 스캔 사용)
기본적으로 옵티마이저는 가능한 경우 인덱스를 사용하지만, FULL을 사용하면 인덱스 대신 전체 테이블을 스캔한다.SELECT /*+ FULL(orders) */ * FROM orders WHERE customer_id = 1001;7.PARALLEL (병렬 처리)
이 힌트는 MySQL이 내부적으로 병렬 실행을 지원하는 경우에 사용한다. (MySQL 8.0 이상에서 지원)SELECT /*+ PARALLEL(4) */ * FROM orders WHERE customer_id = 1001;
NULL 처리
SELECT * FROM 주문 WHERE 배송일자 IS NULL => 인덱스를 사용하지 못한다. SELECT * FROM 주문 WHERE IFNULL(배송일자, '99991231') = '99991231' OR SELECT * FROM 주문 WHERE 배송일자 BETWEEN '00010101' AND '99991231' => 인덱스를 사용한다.
우선적으로 처리 해야하는 연산자
1. = 2. IN 3. BETWEEN 4. LIKE