인덱스 활용

박용민·2025년 2월 26일

INDEX

  1. 공통적으로 사용하는 필수 조건절 컬름을 우선한다.
  2. '=' 조건의 컬럼을 다른 연사자 컬럼보다 우선한다.
  3. 대분류 중분류 소분류 컬럼순으로 구성한다.
  4. 위치(조건) 정보 컬럼은 순서(정렬) 정보 컬럼보다 우선한다.
  5. 조회 건수가 테이블 전체 건수의 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이 해당 연산을 수행하는 동안 읽어야 하는 데이터의 크기 (바이트 단위)

  1. ORDERED
    MySQL은 기본적으로 최적의 조인 순서를 선택하려고 하지만, ORDERED 힌트를 사용하면 쿼리가 지정한 순서대로 테이블을 조인하게 강제할 수 있다.
SELECT /*+ ORDERED */ *
FROM orders, customers
WHERE orders.customer_id = customers.customer_id;
  1. 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

🎉Done

0개의 댓글