인덱스를 적용한 성능 개선
[목차]
1.인덱스?
2.인덱스의 적용조건
3.인덱스의 작동원리
4.인덱스 작성문법
5.프로젝트에 적용하기.
1. 인덱스??
인덱스는 데이터베이스에서 데이터의 검색 및 조회 성능을 향상시키기 위해 사용되는 데이터 구조입니다. 인덱스는 특정 열(또는 열의 조합)에 대한 정렬된 데이터 집합으로, 이를 통해 데이터베이스는 특정 조건에 맞는 레코드를 빠르게 찾을 수 있습니다.
2. 인덱스의 적용조건
인덱스를 적용하기 위해서는 다음과 같은 조건이 필요합니다.
- 카디널리티 (Cardinality)가 높은 열카디널리티는 테이블에서 한 컬럼이 가지고 있는 중복도를 말합니다. 여기에서 카디널리티가 높다는 것은 한 컬럼의 중복도가 낮다는 것을 말합니다.
- 선택도 낮은 열선택도가 낮은 컬럼은 한 컬럼이 갖고 있는 값 하나로 여러 row를 찾을 수 있는지의 여부를 말한다.
- 조회 활용도가 높은 열where 절에 많이 사용되는 컬럼이면 인덱스 적용에 좋은 컬럼이다.
- 수정빈도가 낮은 열
3. 인덱스의 작동원리
인덱스는 기본적으로 B-Tree 기반으로 작동이 됩니다. B-Tree(Balanced Tree) 는 Root블록, Branch 블록,Leaf블록으로 구성이 되어있습니다. Balanced Tree는 모든 Leaf 블록이 동일한 Depth를 유지하도록 하여 균형을 유지합니다. 그러면 데이터 검색을 최대 Depth 이하로 하기 때문에 검색속도를 보장받을 수 있습니다. Leaf Block에서 주황색 선 부분이 있어서 검색을 옆으로 할 수 있어서 매번 Root에서 검색해서 내려올 필요가 없기 때문에 인덱스가 존재하면 그만큼 속도가 더 빠릅니다.
4. 인덱스의 작성문법
인덱스를 작성하는 문법은 다음과 같습니다.
1) 테이블에 있는 인덱스를 확인하는 문법
SHOW INDEX FROM 테이블이름
2) 인덱스를 작성하는 문
ALTER TABLE 테이블이름
ADD INDEX 인덱스이름 (필드이름)
-- 중복을 허용하는 인덱스.
-- 보조 인덱스.
-- 가장 느리지만 인덱스 안한 컬럼 조회하는 것보다 인덱스 붙인 컬럼 조회하는게 더 빠르다. 여러개 노멀키 를 지정할수 있다.
ALTER TABLE 테이블이름
ADD UNIQUE INDEX 인덱스이름 (필드이름)
-- 중복을 허용하지 않는 유일한 키. null 허용.
-- 보조 인덱스.
-- 고속으로 조회 가능
ALTER TABLE 테이블이름
ADD PRIMARY KEY INDEX 인덱스이름 (필드이름)
-- 중복되지 않은 유일한 키. null 비허용.
-- 클러스터 인덱스
-- where로 데이터를 조회할때 가장 고속으로 조회
ALTER TABLE 테이블이름
ADD FULLTEXT INDEX 인덱스이름 (필드이름)
-- 풀텍스트 인덱스
-- 긴 문자열 데이터를 인덱스로 검색할 때 사용.Copy
3) 인덱스 삭제
DROP INDEX 인덱스이름 ON 테이블이름
-- DROP 문은 내부적으로 ALTER 문으로 자동 변환되어 명시된 이름의 인덱스를 삭제
5. 프로젝트에 적용하기.
프로젝트에서 인덱스를 적용하는 방식은 굉장히 단순하다.
@Entity
@Table(name = "board",indexes = {
@Index(name = "index_board_title",columnList = "title",unique = true),
@Index(name = "index_board_author",columnList = "author")})
@Getter
@ToString
@NoArgsConstructor
public class Board {
@Id
@Column(name = "board_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String contents;
private String author;
private Long readCount;
@ToString.Exclude
@JoinColumn(name = "member_id")
@ManyToOne(fetch = FetchType.LAZY)
private Member member;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime createdTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime updatedTime;
@Builder
public Board(Long id,String title,String author,String contents,Long readCount,Member member,LocalDateTime createdTime,LocalDateTime updatedTime){
this.id = id;
this.author = member.getUserId();
this.title = title;
this.contents = contents;
this.readCount = readCount;
this.member = member;
this.createdTime = createdTime;
this.updatedTime = updatedTime;
}
//조회수 증가
public void countUp(){
this.readCount++;
}
}
@Table어노테이션에서 인덱스로 설정하고자 하는 컬럼을 설정만하면 인덱스 설정은 간단하게 끝이다.
그럼 이제 인덱스를 적용 전/후의 성능을 비교해 보자.
테스트로 적용을 할 테이블은 위의 코드에서 볼 수 있듯이 Board테이블이고 더미 데이터로 10만건의 데이터를 넣었고 테스트를 할 sql문은 다음과 같다.
select * from board where title = '';
select * from board where author = '';
적용전 속도
1회 | 2회 | 3회 | 4회 | 5회 | |
제목(title) | 89ms | 85ms | 90ms | 81ms | 83ms |
작성자(author) | 75ms | 82ms | 63ms | 84ms | 69ms |
적용후 속도
1회 | 2회 | 3회 | 4회 | 5회 | |
제목(title) | 96ms | 61ms | 45ms | 47ms | 48ms |
작성자(author) | 71ms | 60ms | 64ms | 66ms | 62ms |
이렇게 적용 전후를 보면 조회를 하는 성능에 있어서 속도가 빨라진 것을 알 수가 있다.
출처: https://smartpro.tistory.com/61 [smartPro for IT:티스토리]