인덱스란?
- 인덱스(Index)란 데이터베이스 테이블에서 데이터 검색을 빠르게 하기 위한 구조이다.
- 테이블에 데이터가 많아지면 검색 속도가 느려지기 때문에, 인덱스를 사용하면 쿼리 성능을 극대화 할 수 있다.
- 인덱스가 없을 경우 쿼리가 Full Table Scan 수행
- 반면 인덱스가 있으면 특정 열에 대해 빠르게 검색 가능.
- 인덱스의 종류 (Types of Indexes)
- B-Tree Index
- B-Tree 구조로 데이터를 정렬하여 검색 속도를 높임
- 대부분의 데이터베이스에서 가장 널리 사용되는 인덱스 형태
- PRIMAL KEY와 UNIQUE KEY는 기본적으로 B-Tree 인덱스이다
- Unique Index
- 중복되지 않는 값만 저장할 수 있다.
- 예) 이메일이나 주민등록번호처럼 유니크한 데이터에 적합하다.
- B-Tree Index
CREATE UNIQUE INDEX idx_email_unique ON customers(email);
- Clustered Index
- 데이터가 물리적으로 정렬된 상태로 저장된다.
- 테이블 당 하나만 생성 가능 (주로 PRIMAL KEY로 사용)
- 검색 시 매우 빠르지만, 테이블 정렬이 자주 변경되면 성능에 영향을 미칠 수 있다.
- Non-Clustered Index
- 데이터 자체는 정렬되지 않지만, 인덱스만 따로 저장된다.
- 한 테이블에 여러 개의 비클러스터형 인덱스를 만들 수 있다.
- Composite Index
- 여러 개의 컬럼을 조합해 인덱스를 생성
- WHERE 조건에 여러 열을 사용할 때 효과적이다.
- 첫 번째 컬럼의 카디널리티가 매우 중요해서, 높은 카디널리티의 컬럼을 앞에 배치하는 것이 좋다.
CREATE INDEX idx_title_board_date ON card (title, board_id, due_date);
- Function-based Index
- 특정 열에 함수를 적용한 결과를 인덱스로 사용한다.
- 예) 이메일 대소문자 구분을 없애기 위해 LOWER(email)을 인덱스에 사용
CREATE INDEX idx_lower_email ON customers (LOWER(email));
카디널리티(Cardinality)와 인덱스 최적화
- 카디널리티(Cardinality)는 특정 컬럼에서 유니크한 값의 개수를 의미한다. 카디널리티가 인덱스 성능에 큰 영향을 미친다
- 카디널리티 유형
- 높은 카디널리티
- 유니크한 값이 많은 경우
- 예) 사용자 ID, 이메일
- 인덱스 효율이 높아 검색 속도가 크게 향상된다.
- 중간 카디널리티
- 예) 날짜 (due_date 등)
- 검색 속도는 유리하지만, 인덱스만으로 성능이 크게 향상되진 않는다.
- 낮은 카디널리티
- 중간 값이 많은 경우
- 예) 상태(status = "ACTIVE", "INACTIVE")
- 인덱스가 비효율적일 수 있으며, 테이블 스캔이 발생할 가능성이 크다.
- 높은 카디널리티
- 카디널리티 확인 방법
SHOW INDEX FROM card;
- 결과 예시
+--------+------------+----------------------------+--------------+-------------+-------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Cardinality |
+--------+------------+----------------------------+--------------+-------------+-------------+
| card | 0 | PRIMARY | 1 | id | 1000000 |
| card | 1 | idx_card_title | 1 | title | 50000 |
| card | 1 | idx_card_board_due_date | 1 | board_id | 10 |
| card | 1 | idx_card_board_due_date | 2 | due_date | 100 |
+--------+------------+----------------------------+--------------+-------------+-------------+
- 복합 인덱스에서의 카디널리티 곱 계산
- 복합 인덱스의 성능은 각 열의 카디널리티를 곱해서 계산할 수 있다.
- 예) board_id + due_date 인덱스
- board_id 의 카디널리티 : 10
- due_date 의 카디널리티 : 100
- 카디널리티 곱 = 10 * 100 = 1000
-> 약 1000개의 유니크 조합을 제공할 수 있다
- 복합 인덱스 설계 팁 :
- 첫 번째 커럼의 카디널리티가 높을수록 인덱스 효율이 좋아진다.
- 첫 번째 컬럼이 낮은 카디널리티면 테이블 스캔이 발생할 수 있습니다.
EXPLAIN과 EXPLAIN ANALYZE의 차이점
EXPLAIN
- 쿼리 실행 전에 실행 계획을 보여준다
- 인덱스 사용 여부를 미리 예측할 수 있다.
EXPLAIN
SELECT * FROM card
WHERE title IN ('카드 제목 1', '카드 제목 2');
EXPLAIN ANALYZE
- 쿼리를 실제로 실행하고 실제 실행 시간과 루프 횟수를 제공한다.
- 인덱스 사용 여부를 명확하게 파악할 수 있다.
- 쿼리가 오래 걸리는 경우에는 최적화가 필요하다.
EXPLAIN ANALYZE
SELECT * FROM card
WHERE title IN ('카드 제목 1', '카드 제목 2');
실행 계획 예시
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Index range scan on card using idx_card_title (title in ('카드 제목 1', '카드 제목 2')) (cost=1.86 rows=2) (actual time=0.02..0.03 rows=2) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
Index range scan : 인덱스를 사용해 범위 스캔을 수정한다.
cost : 쿼리 실행 비용 (낮을수록 좋음)
rows : 예상되는 결과 수
actual time : 실제 실행 시간
loops : 쿼리 반복 횟수
'스프링' 카테고리의 다른 글
Rest Template과 JDBC Template (4) | 2024.10.20 |
---|---|
스프링 인증/인가..! JWt..? (0) | 2024.09.10 |
Spring 인증 및 관리 시스템 (0) | 2024.09.06 |
[TroubleShooting] 의존성 주입,,,실패하다,, (1) | 2024.08.29 |
Spring JPA 뭐하는 키워드지..? (1) | 2024.08.24 |