MySQL 8.0에서 추가된 모든 기능 – 인덱스

MySQL 8.0에서 추가된 모든 기능들과 변경된 기능들에 대해 정리한 시리즈 문서로, 이 문서는 인덱스에 대한 내용을 담고있습니다. INDEX 관련 주요 변경 사항들을 살펴봅시다.
1. 보이지 않는 인덱스
보이지 않는 인덱스(Invisible Index)는 인덱스를 생성하거나 유지하면서도 옵티마이저에게 해당 인덱스를 사용하지 않도록 설정할 수 있는 기능입니다. 인덱스를 삭제하지 않고도 비활성화할 수 있어, 인덱스의 성능 영향도를 테스트하거나, 향후 다시 사용할 가능성이 있는 인덱스를 보관할 때 유용합니다.
예시:
-- 인덱스 생성 시 INVISIBLE 옵션 사용
CREATE INDEX idx_employee_name ON employees(name) INVISIBLE;
-- 기존 인덱스를 보이지 않게 변경
ALTER TABLE employees ALTER INDEX idx_employee_name INVISIBLE;
-- 인덱스를 다시 보이게 변경
ALTER TABLE employees ALTER INDEX idx_employee_name VISIBLE;
이 예시에서는 employees
테이블의 name
컬럼에 대한 인덱스를 생성하면서 INVISIBLE
옵션을 사용하여 옵티마이저가 해당 인덱스를 사용하지 않도록 합니다.
2. 내림차순 인덱스
[원본제공링크 1]
내림차순 인덱스(Descending Index)는 인덱스의 키 값을 내림차순(DESC)으로 저장하는 기능입니다. 기존에는 인덱스가 항상 오름차순(ASC)으로만 저장되었지만, 내림차순 인덱스를 사용하면 ORDER BY 절에서 내림차순 정렬 시 성능을 향상시킬 수 있습니다.
예시:
-- 내림차순 인덱스 생성
CREATE INDEX idx_order_date_desc ON orders(order_date DESC);
-- 복합 인덱스에서 내림차순 지정
CREATE INDEX idx_customer_order ON orders(customer_id, order_date DESC);
이 예시에서는 orders
테이블의 order_date
컬럼에 대한 내림차순 인덱스를 생성하여, 최근 주문을 조회할 때 성능을 개선합니다.
3. 함수 인덱스
[원본제공링크 1]
함수 인덱스(Functional Index)는 인덱스를 생성할 때 컬럼의 값에 함수나 표현식을 적용한 결과를 기반으로 인덱싱하는 기능입니다. 이를 통해 대소문자 구분 없이 검색하거나, 부분 문자열 또는 계산된 값에 대한 검색 성능을 향상시킬 수 있습니다.
예시:
-- LOWER 함수를 사용한 함수 인덱스 생성
CREATE INDEX idx_employee_name_lower ON employees(LOWER(name));
-- 계산된 값을 사용하는 함수 인덱스 생성
CREATE INDEX idx_product_discount ON products(price * (1 - discount_rate));
이 예시에서는 name
컬럼의 소문자 값을 인덱싱하여 대소문자에 관계없이 빠르게 검색할 수 있도록 합니다.
4. 인덱스 스킵 스캔
[원본제공링크 1]
인덱스 스킵 스캔(Index Skip Scan)은 복합 인덱스의 선행 컬럼이 아닌 후행 컬럼을 사용한 조건에서도 인덱스를 활용할 수 있게 해주는 옵티마이저의 기능입니다. 이를 통해 기존에는 풀 테이블 스캔을 수행하던 쿼리에서도 인덱스 스캔을 활용하여 성능을 개선할 수 있습니다.
예시:
-- 복합 인덱스 생성 (선행 컬럼: employee_id, 후행 컬럼: department_id)
CREATE INDEX idx_skipscan_test ON employees(employee_id,department_id);
-- 선행 컬럼 없이 후행 컬럼만 조건으로 사용
EXPLAIN SELECT department_id FROM employees WHERE department_id >= 104;
-- 잘 안되면 힌트넣고 확인해보세요
EXPLAIN SELECT /*+ SKIP_SCAN(employees idx_skipscan_test) */ department_id FROM employees WHERE department_id >= 104;
이 쿼리는 기존에는 department_id
만으로는 인덱스를 사용할 수 없었지만, 인덱스 스킵 스캔을 통해 idx_skipscan_test 인덱스를 활용하여 성능을 향상시킵니다.
+----+-------------+-----------+------------+-------+-------------------+-------------------+---------+------+------+----------+----------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+-------------------+-------------------+---------+------+------+----------+----------------------------------------+
| 1 | SIMPLE | employees | NULL | range | idx_skipscan_test | idx_skipscan_test | 9 | NULL | 8 | 100.00 | Using where; Using index for skip scan |
+----+-------------+-----------+------------+-------+-------------------+-------------------+---------+------+------+----------+----------------------------------------+
1 row in set, 1 warning (0.00 sec)
5. 인덱스 힌트 USE / IGNORE / FORCE INDEX
[원본제공링크 1]
인덱스 힌트(Index Hint)는 쿼리에서 옵티마이저에게 특정 인덱스를 사용하거나 사용하지 않도록 지시하는 방법입니다. USE INDEX
, IGNORE INDEX
, FORCE INDEX
등의 힌트를 통해 쿼리 실행 계획을 튜닝할 수 있습니다.
예시:
-- 특정 인덱스를 사용하도록 지시
SELECT * FROM employees USE INDEX (idx_employee_name) WHERE name = 'Alice';
-- 특정 인덱스를 무시하도록 지시
SELECT * FROM employees IGNORE INDEX (idx_employee_name) WHERE name = 'Alice';
-- 특정 인덱스의 사용을 강제
SELECT * FROM employees FORCE INDEX (idx_employee_name) WHERE name = 'Alice';
이 예시에서는 employees
테이블에서 idx_employee_name
인덱스의 사용을 지시하거나 무시하거나 강제하여 옵티마이저의 실행 계획에 영향을 줍니다.