ComputerScience/DB

인덱스를 적용한 성능 개선

slown 2024. 4. 6. 18:52

[목차]

1.인덱스?

2.인덱스의 적용조건

3.인덱스의 작동원리 

4.인덱스 작성문법

5.프로젝트에 적용하기. 

 

1. 인덱스??

인덱스데이터베이스에서 데이터의 검색 및 조회 성능을 향상시키기 위해 사용되는 데이터 구조입니다. 인덱스는 특정 열(또는 열의 조합)에 대한 정렬된 데이터 집합으로, 이를 통해 데이터베이스는 특정 조건에 맞는 레코드를 빠르게 찾을 수 있습니다.

2. 인덱스의 적용조건

인덱스를 적용하기 위해서는 다음과 같은 조건이 필요합니다. 

  1. 카디널리티 (Cardinality)가 높은 열카디널리티는  테이블에서 한 컬럼이 가지고 있는 중복도를  말합니다. 여기에서 카디널리티가 높다는 것은 한 컬럼의 중복도가 낮다는 것을 말합니다.
  2. 선택도 낮은 열선택도가 낮은 컬럼은 한 컬럼이 갖고 있는 값 하나로 여러 row를 찾을 수 있는지의 여부를 말한다.
  3. 조회 활용도가 높은 열where 절에 많이 사용되는 컬럼이면 인덱스 적용에 좋은 컬럼이다.
  4. 수정빈도가 낮은  열

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:티스토리]