인덱스(Index)란?
인덱스(Index)는 데이터베이스 테이블의 특정 열(Column)에 대한 검색 속도를 향상시키기 위한 자료구조로, 책의 목차처럼 데이터를 빠르게 찾을 수 있도록 돕는 역할을 한다.
주요 특징
- 빠른 검색: 데이터베이스는 인덱스를 통해 필요한 데이터를 빠르게 찾을 수 있다.
- 추가 저장 공간 필요: 인덱스는 테이블과 별도로 저장되기 때문에 추가적인 저장 공간이 필요하다.
- 쓰기 성능 저하: 데이터 삽입, 업데이트, 삭제 시 인덱스도 함께 갱신되어야 하므로 쓰기 성능이 저하될 수 있다.
장점
- 쿼리 성능 향상
- 인덱스를 사용하면 데이터를 빠르게 검색할 수 있어 SELETE 쿼리 성능이 크게 향상된다.
- 특히, 대량의 데이터에서 특정 조건에 맞는 데이터를 효율적으로 찾을 수 있다.
- 정렬 성능 향상
- 인덱스를 사용하면 데이터가 이미 정렬된 상태로 유지되므로 ORDER BY 절의 성능이 개선된다.
- JOIN 및 GROUP BY 성능 향상
- 테이블 간 JOIN 및 GROUP BY, DISTINCT 같은 연산의 처리 속도가 빨라진다.
- 빠른 범위 검색
- BETWEEN, <, > 등의 범위 조건을 효율적으로 처리할 수 있다.
단점
- 쓰기 성능 저하
- INSERT, UPDATE, DELETE와 같은 쓰기 작업 시 인덱스도 갱신되어야 하므로 오버헤드가 발생한다.
- 데이터가 자주 변경되는 테이블에 인덱스가 많으면 성능 저하가 심할 수 있다.
- 추가적인 저장 공간 필요
- 인덱스를 저장하기 위한 추가적인 디스크 공간(DB의 약 10%)이 필요하다.
- 대규모 테이블에 다수의 인덱스를 생성하면 저장소 사용량이 증가한다.
- 복잡성 증가
- 어떤 열에 인덱스를 적용해야 하는지 신중히 설계해야 하며, 잘못 설계된 인덱스는 성능을 저하시킬 수 있다.
- 과도한 인덱스 생성
- 너무 많은 인덱스를 생성하면 쿼리 최적화 과정에서 오히려 오버헤드가 발생할 수 있다.
- 인덱스 유지 비용
- 테이블의 데이터가 변경될 때마다 인덱스를 유지하기 위한 추가 작업이 수행된다.
※ 참고
데이터베이스의 인덱스(Index)는 주로 WHERE 조건절이나, JOIN 조건, GROUP BY, ORDER BY 등에 사용되는 경우 성능을 향상시키기 위해 설계되었다. 단순히 SELECT 절에 특정 열을 포함한다고 하여 인덱스가 적용되지 않는다.
인덱스 구조
인덱스는 일반적으로 B-Tree 또는 B+Tree, Hash Table 구조를 기반으로 동작한다.
B-Tree 인덱스
구조
- B-Tree는 데이터베이스와 파일 시스템에서 가장 널리 사용되는 인덱스 유형으로 균형 트리의 일반화된 구조이며, 데이터가 정렬된 상태로 저장된다.
- 루트 노드부터 내부 노드, 리프 노드까지 모든 경로의 길이가 동일하다.
- 노드: 각 노드는 키(Key)와 포인터(Pointer)를 포함한다.
- 키: 데이터를 나타내며, 특정 범위의 값을 찾는 데 사용된다.
- 포인터: 자식 노드 또는 데이터의 실제 위치를 가리킨다.
- 데이터를 여러 노드에 저장하며, 검색, 삽입, 삭제 시 노드가 분할되거나 병합될 수 있다.
- 자식 노드가 여러 개일 수 있으며, 항상 균형 상태를 유지한다.
※ 균형 트리(Balanced Tree)
데이터베이스 인덱스에서 사용되는 균형 트리는 트리의 모든 노드에서 좌우 서브트리의 높이 차이가 일정 범위 내로 유지되는 트리 구조이다. 이 구조는 검색, 삽입, 삭제 작업에서 효율성을 보장하기 위해 설계되었다.
특징
1. 높이 균형 유지
- 모든 리프 노드는 동일한 깊이를 가지며, 트리의 높이가 최소화된다.
- 이는 데이터 접근 시간을 줄이고 성능을 최적화한다.
2. 시간 복잡도 보장
- 겁색, 삽입, 삭제 연산은 모두 O(logN)의 시간 복잡도를 가진다.
- 데이터가 많아져도 성능이 크게 저하되지 않는다.
3. 트리 높이 최소화
- 노드에 데이터를 다수 저장하여 트리의 높이를 줄이고 디스크 I/O를 최소화한다.
균형 트리의 활용
데이터베이스에서는 B-Tree와 B+Tree가 균형 트리의 개념을 활용해 구현된다.
- B-Tree: 각 노드가 여러 키와 포인터를 포함하며, 삽입/삭제 시 노드 분할과 병합을 통해 균형을 유지한다.
- B+Tree: 데이터는 리프 노드에만 저장되며, 리프 노드가 링크드 리스트 형태로 연결되어 범위 검색이 효율적이다.
동작 원리
DBMS는 Index를 항상 최신의 정렬된 상태로 유지해야 원하는 값을 빠르게 탐색할 수 있다.
그렇기에 인덱스가 적용된 컬럼에 삽입, 삭제, 조회 등이 수행된다면 다음 연산을 추가로 해주어야 하므로 오버헤드가 발생한다.
- 검색(Search): 루트 노드에서 시작하여 키의 범위를 확인한 뒤, 적절한 자식 노드로 이동한다. 리프 노드에 도달할 때까지 반복하며 원하는 데이터를 찾는다.
- 삽입(Insertion): 새로운 키는 적절한 위치에 삽입된다. 노드가 초과(Overflow)되면 분할(Split)이 발생하여 트리가 균형을 유지한다.
- 삭제(Deletion): 키가 삭제되면 노드가 비거나 부족(Underflow)할 수 있으며, 병합(Merge) 또는 재분배(Restribution)로 균형을 맞춘다.
※ 참고
대부분의 최신 데이터베이스 시스템에서는 인덱스를 수정하거나 삭제할 때 기존 인덱스가 물리적으로 즉시 삭제되지 않고 사용되지 않음(또는 무효화됨)으로 표시되는 경우가 많다. 이 접근 방식은 데이터베이스 무결성을 유지하고 중단을 방지하며 성능을 향상시키기 위해 사용된다.
색인 수정 및 삭제 작동 방식
1. 미사용으로 표시(소프트 삭제)
- 인덱스가 수정되거나 삭제되면 데이터베이스 엔진은 일반적으로 해당 인덱스를 사용되지 않거나 유효하지 않은 것으로 표시한다.
- 인덱스 데이터는 여전히 디스크에 존재하지만 더 이상 쿼리 실행에 사용되지 않는다.
- 이 접근 방식은 작업 중 우발적인 데이터 손실을 방지하고 필요한 경우 롤백을 허용한다.
2. 인덱스 재작성
- 수정의 경우 일반적으로 업데이트된 사양(예: 새 열, 정렬 순서 등)을 사용하여 새 인덱스가 생성된다.
- 이 과정에서 새 인덱스가 완전히 구축되어 사용할 준비가 될 때까지 이전 인덱스는 그대로 유지된다. 이를 통해 데이터베이스 작업 중단을 최소화할 수 있다.
- 새 인덱스가 생성되면 쿼리 계획의 이전 인덱스가 대체된다.
3. 물리적 정리(가비지 수집)
- 오래되고 사용되지 않는 인덱스는 결국 정리 과정을 통해 디스크에서 제거된다.
- 많은 데이터베이스 시스템에는 디스크 공간을 확보하기 위해 이 정리를 처리하는 백그라운드 작업이나 유지 관리 프로세스가 있다(예: PostgreSQL의 진공 또는 SQL Server의 온라인 인덱스 정리).
이 접근 방식의 장점
1. 비차단 작업
- 새 인덱스가 준비될 때까지 이전 인덱스를 유지함으로써 데이터베이스는 수정 또는 삭제 프로세스 중에 인덱스에 의존하는 쿼리가 중단되지 않도록 보장한다.
2. 롤백 기능
- 인덱스 수정이나 삭제가 도중에 실패하는 경우, 데이터베이스는 데이터 손실이나 다운타임 없이 이전 인덱스로 되돌릴 수 있다.
3. 효율적인 자원 활용
- 데이터베이스 엔진은 사용되지 않는 인덱스의 물리적 삭제를 덜 바쁜 시간으로 연기하여 라이브 쿼리 성능에 미치는 영향을 줄일 수 있다.
물리적 삭제는 언제 발생하는가?
- 물리적 삭제는 일반적으로 유지 관리 기간 동안 또는 데이터베이스가 사용되지 않은 공간을 회수하기로 결정할 때 발생한다.
- 일부 시스템에서는 디스크 공간을 더 빨리 회수하려는 경우 수동 정리 트리거(예: 'VACUUM' 또는 'OPTIMIZE' 명령)를 허용한다.
장점
- 노드가 정렬된 상태로 유지되어 범위 검색이 가능하다.
- 삽입, 삭제 시에도 균형을 유지하므로 성능이 일정하다.
단점
- 리프 노드 외의 내부 노드에도 데이터를 저장하기에, 대규모 데이터에서는 디스크 I/O가 많아질 수 있다.
사용 사례
- 일반적인 데이터베이스 인덱스 및 파일 시스템에서 사용된다.
B+Tree
B+Tree는 B-Tree의 확장된 버전으로, 데이터베이스 인덱스에서 더 자주 사용된다. 특히 범위 검색(Range Query)에서 유리한 특성을 가진다.
구조
- B-Tree의 확장된 형태로, 모든 데이터는 리프 노드에만 저장된다.
- 리프 노드가 서로 연결된, 정렬된 링크드 리스트 구조로 되어 있어, 범위 검색이 효율적이다.
- 내부 노드는 데이터 대신 리프 노드의 포인터와 키 정보만 저장한다.
- 디스크 접근을 최소화하며 대량의 데이터를 처리하는 데 적합합니다.
※ B+Tree가 디스크 접근을 최소화 할 수 있는 이유!!
1. 디스크 블록에 최적화된 구조
B+Tree는 데이터베이스 인덱스로 설계될 때, 각 노드의 크기를 디스크의 블록 크기(block size)에 맞게 조정한다. 이를 통해 하나의 디스크 읽기(한 블록의 읽기)로 여러 키와 포인터를 한 번에 가져올 수 있다.
- 디스크는 메모리보다 훨씬 느리기 때문에, 디스크 접근 횟수를 줄이는 것이 성능 최적화의 핵심이다.
- B+Tree의 노드에는 다수의 키와 자식 노드 포인터가 저장되므로, 한 번의 디스크 읽기로 검색에 필요한 대부분의 데이터를 가져올 수 있다.
2. 트리의 낮은 높이
B+Tree는 노드당 다수의 키를 저장할 수 있으므로, 같은 양의 데이터를 저장하는 이진 트리나 다른 트리 구조보다 트리의 높이가 낮다.
- 트리 높이가 낮으면, 특정 데이터를 검색할 때 루트에서 리프 노드까지 접근해야 하는 디스크 읽기 횟수가 줄어든다.
- 예를 들어, 수백만 개의 데이터를 저장하더라도 B+Tree는 일반적으로 3~5단계의 높이만 가진다.
3. 리프 노드 연결로 범위 검색 최적화
B+Tree의 리프 노드들은 링크드 리스트로 연결되어 있다. 따라서 범위 검색 시 리프 노드 간 이동만으로 데이터를 순차적으로 읽을 수 있다.
- 디스크 I/O가 발생하는 경우는 리프 노드에 한정되므로, 검색 성능이 향상된다.
- 범위 검색 중에도 트리 전체를 탐색할 필요 없이 리프 노드에서 필요한 데이터만 순차적으로 읽으면 된다.
4. 내부 노드는 인덱스 역할만 수행
B+Tree에서 실제 데이터는 리프 노드에만 저장되며, 내부 노드는 검색을 위한 인덱스 키와 포인터만 저장한다.
- 내부 노드가 상대적으로 작으므로, 메모리에 더 많은 내부 노드를 유지할 수 있다.
- 검색 시 메모리에서 내부 노드 탐색이 이루어지고, 리프 노드에만 디스크 접근이 이루어지므로 디스크 I/O를 최소화할 수 있다.
5. 노드 분할과 병합 과정의 중요성
삽입 및 삭제 시, B+Tree는 노드가 가득 찰 경우 분할, 노드가 너무 비어있을 경우 병합을 통해 트리의 균형을 유지한다.
- 이러한 동작은 디스크 접근을 최소화하도록 설계되어, 삽입/삭제 연산이 이루어질 때에도 성능 저하를 방지한다.
장점
- 리프 노드가 정렬되고 연결되어 있으므로 범위 검색에서 매우 효율적이다.
- 내부 노드에 데이터를 저장하지 않으므로 디스크 I/O가 감소한다.
단점
- 데이터 구조가 약간 더 복잡하며, 메모리 사용량이 늘어날 수 있다.
사용 사례
- 데이터베이스에서 주요 인덱스 구조로 가장 널리 사용된다.
Hash Table
Hash Table은 해시 함수를 사용하여 데이터를 저장하고 검색하는 매우 빠른 데이터 구조이다. 특히 정확한 키 검색에서 성능이 뛰어나다.
구조
- 해시 함수를 사용하여 키를 해시 값으로 변환한 뒤, 데이터를 저장할 버킷(bucket)을 결정한다.
- 충돌(Collision)이 발생할 경우, 체이닝(Chaning) 또는 오픈 어드레싱(Open Addressing) 방법으로 해결한다.
동작 원리
- 검색(Search): 키를 해시 함수에 입력하여 데이터가 저장된 버킷을 빠르게 찾는다.
- 삽입(Insertion): 키를 해시 함수에 입력하여 적절한 버킷에 데이터를 저장한다.
- 삭제(Deletion): 키를 통해 데이터를 검색한 뒤, 해당 데이터를 삭제한다.
장점
- 정확한 키 검색에서 매우 빠른 성능을 제공하며, 평균 검색 속도는 O(1)이다.
- 구현이 상대적으로 간단하다.
단점
- 범위 검색이 불가능하며, 정렬된 데이터를 처리할 수 없다.
- 해시 충돌로 인해 성능 저하가 발생할 수 있으며, 버킷 관리가 필요하다.
사용 사례
- 정확한 키 기반 데이터 검색(예: 캐시, 메모리 기반 데이터 저장소)에서 사용된다.
B-Tree vs. B+Tree vs. Hash Table
특성 | B-Tree | B+Tree | Hash Table |
검색 속도 | O(log N) | O(log N) | O(1) |
삽입/삭제 속도 | O(log N) | O(log N) | O(1) |
범위 검색 | 가능 | 매우 효율적 | 불가능 |
정렬된 데이터 처리 | 가능 | 가능 | 불가능 |
디스크 I/O | 상대적으로 많음 | 상대적으로 적음 | 없음 (메모리 기반 시) |
사용 사례 | 일반적인 인덱스 | 범위 검색, 대용량 데이터 | 키 기반 검색, 캐싱 |
인덱스 제약 조건 & 용도
데이터베이스의 인덱스 제약 조건은 인덱스를 활용해 데이터 무결성을 보장하거나 특정 조건을 만족하도록 하는 규칙이다.
인덱스 자체는 쿼리 성능을 향상시키는 도구지만, 제약 조건과 결합되면 데이터의 품질과 일관성을 유지하는 데 중요한 역할을 한다.
기본 키 인덱스 (Primay Key Index)
기본 키는 자동으로 클러스터형 인덱스(Clustered Index)를 생성하며, 데이터 무결성을 보장한다.
- 고유성 보장: 기본 키는 테이블 내에서 중복된 값이 존재할 수 없다.
- NULL 값 불허: 기본 키 컬럼에는 NULL 값을 삽입할 수 없다.
- 자동 인덱스 생성: 기본 키를 설정하면 자동으로 인덱스가 생성된다.
- 단일 또는 복합 컬럼 가능: 하나의 컬럼뿐만 아니라 여러 컬럼으로 구성된 복합 키도 가능하다.
예제
CREATE TABLE users (
user_id INT AUTO_INCREMENT PRIMARY KEY, -- 고유 식별자 (Primary Key)
name VARCHAR(50) NOT NULL, -- 사용자 이름
age INT NOT NULL, -- 나이
email VARCHAR(100) UNIQUE, -- 이메일 (Unique)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 생성 시간
);
- 기본 키 인덱스는 user_id를 기준으로 사용자를 고유하게 식별할 수 있다.
쿼리
SELECT * FROM users WHERE user_id = 101;
복합 인덱스 (Multi Column Index)
두 개 이상의 컬럼을 결합하여 생성된 인덱스로, 특정 조건에 대한 검색, 정렬, 그리고 필터링의 성능을 개선할 수 있다.
- 검색 효율성 향상: 여러 컬럼에 대한 조건을 포함하는 쿼리에서 성능을 극대화한다.
- 순서 중요: 복합 인덱스는 컬럼의 순서에 따라 작동한다. 인덱스가 (A, B)로 생성되었다면, A 컬럼이 검색 조건에 반드시 포함되어야 한다.
- 조건의 조합: 복합 인덱스는 결합된 컬럼들의 특정 조합을 빠르게 조회할 수 있다.
예제
CREATE TABLE orders (
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
order_date DATE,
amount DECIMAL(10, 2),
INDEX idx_customer_order_date (customer_id, order_date)
);
- 복합 키 (customer_id, order_date)에 대해 인덱스가 생성된다.
쿼리
SELECT * FROM orders WHERE customer_id = 10 AND order_date = '2024-01-01';
복합 인덱스 설계 시 주의점
- 쿼리 패턴 고려: 자주 사용되는 WHERE 조건의 순서에 맞춰 설계한다.
- 컬럼 순서 중요: 인덱스가 (A, B)로 설정되면 B만 단독으로 검색할 경우 비효율적이다.
- 최적화 도구 활용: 실행 계획(EXPLAIN)을 통해 인덱스가 제대로 활용되고 있는지 확인한다.
특징 | 기본 키 | 유니크 인덱스 | 복합 인덱스 |
중복 허용 여부 | 중복 불가 | 중복 불가 | 중복 가능 |
NULL 허용 여부 | NULL 불가 | NULL 허용 | NULL 허용 |
사용 목적 | 행 고유 식별 | 고유성 보장 및 검색 성능 향상 | 다중 컬럼 조회의 검색 성능 향상 |
자동 생성 여부 | 자동 생성 | 수동 생성 | 수동 생성 |
인덱스 저장 방식
클러스터드(Clustered)와 논 클러스터드(Non-Clustered) 인덱스는 데이터가 물리적으로 어떻게 저장되고 관리되는지를 결정하는 핵심적인 개념이다.
클러스터드 인덱스 (Clustered Index)
- 클러스터드 인덱스는 테이블의 데이터가 인덱스의 순서에 따라 물리적으로 정렬되어 저장된다.
- 테이블당 하나의 클러스터드 인덱스만 생성할 수 있다(데이터 자체가 정렬되기 때문).
특징
- 데이터와 인덱스가 일치: 클러스터드 인덱스의 리프 노드가 실제 데이터 페이지를 가리킨다.
- 기본 키와 연계: 대부분의 경우 기본 키(Primary Key)가 클러스터드 인덱스로 설정된다.
장•단점
- 장점
- 범위 검색에 뛰어남: 데이터를 정렬된 상태로 저장하기 때문에 BETWEEN, <, > 같은 범위 검색에 최적화되어 있다.
- 빠른 검색 성능: 검색 결과를 찾은 후 추가적인 데이터 접근이 필요 없다(데이터가 인덱스에 포함되어 있기 때문).
- 단점
- 삽입/삭제 비용 증가: 데이터를 물리적으로 정렬된 상태로 유지해야 하므로, 데이터 변경 작업(INSERT, UPDATE, DELETE)에 비용이 더 든다.
- 테이블당 하나만 생성 가능하다.
논 클러스터드 인덱스 (Non-Clustered Index)
- 논 클러스터드 인덱스는 데이터와 별도로 저장된 인덱스 구조이다.
- 인덱스에는 키 값과 함께 해당 키 값이 위치한 데이터의 주소(포인터)가 저장된다.
특징
- 하나의 테이블에 여러 개의 논 클러스터드 인덱스를 생성할 수 있다.
- 논 클러스터드 인덱스의 리프 노드는 실제 데이터가 아닌 데이터 페이지의 참조를 포함한다.
장•단점
- 장점
- 여러 인덱스 생성 가능: 테이블에 대해 다양한 조회 패턴을 지원하기 위해 여러 개의 논 클러스터드 인덱스를 만들 수 있다.
- 쓰기 작업 부담 적음: 클러스터드 인덱스에 비해 데이터 정렬이 필요 없기 때문에 쓰기 작업에서 더 유연하다.
- 단점
- 추가적인 데이터 접근 필요: 논 클러스터드 인덱스를 통해 데이터를 찾은 후 실제 데이터 페이지를 참조해야 하기 때문에 추가적인 I/O가 발생할 수 있다.
- 저장 공간 증가: 데이터와 별도로 인덱스를 저장하기 대문에 추가적인 저장 공간이 필요하다.
인덱스는 언제 사용하면 좋을까?
인덱스는 데이터 검색 성능을 향상시키는 데 필수적이지만, 모든 경우에 사용하는 것이 적합하지는 않다.
인덱스를 효율적으로 설계하려면 데이터 구조와 쿼리 패턴을 잘 분석하고, 인덱스를 사용해야 하는 경우와 피해야 하는 경우를 명확히 구분하는 것이 중요하다.
1. 자주 검색되는 컬럼
- 조건: WHERE 절에 자주 사용되는 컬럼
- 설명: 특정 값을 조건으로 검색할 때 인덱스가 데이터를 빠르게 찾을 수 있도록 도와준다.
SELECT * FROM employees WHERE department_id = 5;
2. 자주 정렬(ORDER BY)되는 컬럼
- 조건: ORDER BY 절에 자주 사용되는 컬럼
- 설명: 정렬된 데이터를 반환할 때 인덱스가 데이터를 미리 정렬된 상태로 유지하여 성능을 향상시킨다.
SELECT * FROM employees ORDER BY hire_date DESC;
3. JOIN에 사용되는 컬럼
- 조건: 테이블 간 JOIN 조건에 사용되는 컬럼
- 설명: 두 테이블 간 연결(JOIN)을 수행할 때, 인덱스를 사용하면 검색 속도가 향상된다.
SELECT e.name, d.name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;
4. GROUP BY나 DISTINCT에 사용되는 컬럼
- 조건: GROUP BY 또는 DISTINCT가 자주 사용되는 커럶
- 설명: 중복된 데이터를 그룹화하거나 고유 데이터를 반환할 때, 인덱스를 통해 성능을 최적화할 수 있다.
SELECT department_id, COUNT(*)
FROM employees
GROUP BY department_id;
5. 범위 검색
- 조건: BETWEEN, <, >, <=, >= 같은 연산이 자주 사용되는 컬럼
- 설명: 범위 조건이 포함된 쿼리는 B-Tree 인덱스를 통해 효율적으로 처리할 수 있다.
SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-01-31';
인덱스를 활용할 수 없는 경우
LIKE 조건이 와일드카드로 시작하는 경우
LIKE 키워드의 사용 방식과 패턴에 따라 인덱스 활용 여부가 달라진다.
패턴이 접두사 매칭인 경우 (Index 사용 가능)
LIKE의 패턴이 문자열의 시작 부분에 고정된 경우 인덱스를 사용할 수 있다.
SELECT * FROM users WHERE username LIKE 'john%';
- 문자열이 'john'으로 시작하는 조건에서 B-Tree 인덱스를 활용할 수 있다.
- 접두사 매칭은 정렬된 인덱스 범위 내에서 검색할 수 있기 때문이다.
패턴이 전체 또는 접미사 매칭인 경우 (Index 사용 불가능)
패턴이 문자열의 끝부분이나 중간에 있는 경우 인덱스를 사용할 수 없다.
SELECT * FROM users WHERE username LIKE '%john';
SELECT * FROM users WHERE username LIKE '%john%';
- 앞부분에 와일드카드(%)가 포함된 조건에서는 인덱스를 사용할 수 없다.
- 앞부분의 값을 알 수 없기 때문에 데이터 전체를 스캔해야 한다.
LIKE와 함수 사용 (Index 사용 불가)
LIKE와 함께 문자열 함수를 사용하는 경우 인덱스 활용이 불가능하다.
SELECT * FROM users WHERE LOWER(username) LIKE 'john%';
- 함수가 적용된 컬럼은 인덱스 정보를 활용하지 못하므로 전체 테이블 스캔이 발생한다.
- 컬럼을 변환하지 않고 데이터 저장 시 소문자로 변환하거나, 함수 기반 인덱스를 사용한다.
'개인 학습 > DataBase' 카테고리의 다른 글
MySQL filesort (0) | 2024.12.30 |
---|---|
ORDER BY와 인덱스의 관계 + sort_buffer_size (0) | 2024.12.27 |
Covering Index (0) | 2024.12.23 |
EXPLAIN을 활용한 SQL 쿼리 성능 분석 방법 (0) | 2024.12.22 |
Multi Column Index (0) | 2024.12.10 |