Post

데이터베이스 인덱스

Index

소개

인덱스는 테이블의 컬럼 색인화, 책의 목차 기능을 제공한다. 데이터 정렬 후 별도의 메모리 공간에 저장하는데, 이 형태는 컬럼 값(key), 물리 주소(value)로 설정된다.

목적

first_nameage
kim15
lee30
park25
lee20
park10

다음과 같은 자료가 있다고 가정해보자. 만약 인덱스가 없다면 다음과 같은 쿼리를 실행했을 경우 데이터베이스를 모두 스캔해야 한다.

1
SELECT first_name FROM 'TABLE' WHERE age = 20

하지만 인덱스가 있다면, 인덱스 테이블에서 해당 자료의 위치를 빠르게 찾아 결과를 빠르게 탐색할 수 있다. 인덱스 존재 유무에 따른 속도 테스트를 진행해 보았다. 코드는 다음과 같다.

Entity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Table(indexes = {@Index(name = "test_index",columnList = "first_name")}) 
// 해당 어노테이션을 기입, 제거하는 방식으로 진행했다. 

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Builder
public class TestEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "first_name")
    private String firstName;
}

Test Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class DBTest {

    @Autowired
    private TestRepository testRepository;

    @BeforeAll
    void init(){
        for(long i = 0; i < 1000000; i++){
            TestEntity test = TestEntity.builder()
                    .firstName("kim" + i)
                    .build();
            testRepository.save(test);
        }

    }

    @AfterAll
    void release(){
        testRepository.deleteAll();
    }

    @ParameterizedTest
    @ValueSource(ints = {1,2,3,4,5,6,7,8,9,10})
    void test(int count){
        testRepository.findByFirstName("kim" + count);
    }
}


결과는 다음과 같다.

인덱스 존재

인덱스

인덱스 없음

없음

인덱스의 존재 유무에 따라 차이가 확연한 것을 볼 수 있다.

장점

  • 검색 속도 및 성능 향상(조건부)

인덱스는 정렬된 형태의 데이터를 가지기 때문에, 인덱스를 통해 테이블 검색 속도가 향상되고 이는 전반적인 어플리케이션의 성능 향상으로 이어질 수 있다. 하지만 반드시 인덱스를 설정한다고 모든 프로그램의 성능이 좋아지리라는 보장은 없다.

단점

  • 잦은 데이터 수정 시 성능 저하

테이블의 데이터를 수정 시 인덱스의 내용도 수정되어야 한다. 이는 삽입 및 수정이 빈번한 경우에는 오히려 더 큰 부하로 작용할 수 있다.

  • 데이터 제거 시 인덱스는 제거되지 않음

테이블에서 데이터가 삭제되어도, 인덱스 테이블에서는 ‘사용하지 않음’ 처리 후 데이터를 남겨둔다고 한다. 이는 실제 데이터에 비해 인덱스 과도하게 커지는 문제점이 발생할 수 있다.

  • 검색 성능 저하

인덱스를 잘못된 컬럼에 걸어 놓으면 오히려 성능이 저하될 수 있다. 나이, 성별과 같은 값의 범위가 좁은 경우에는 인덱스를 확인해도 어차피 다시 많은 데이터를 조회해야 하기 때문이다.

사용하면 좋은 경우

데이터의 수정 및 삭제가 자주 발생하지 않으며, 검색과 같은 조회가 잦고, 데이터의 중복도가 낮은 컬럼을 인덱스로 사용하면 큰 효과를 볼 수 있다.

내부 구현

key, value로 이루어져 있기 때문에 해시테이블 같은 자료구조를 떠올리기 쉬우나, 해시테이블의 특성상 등호(==) 연산에만 최적화 되어있고, 부등호(>, <) 연산에는 취약하므로 잘 사용되지 않는다고 한다. 실제 구현은 검색 범위를 좁히기도 쉽고, 범위 검색에도 좋은 B+ 트리를 사용한다고 한다.

B+ Tree

B+ 트리는 오직 leaf node에만 데이터를 저장한다. leaf node가 아닌 node에서는 자식의 포인터만 저장하고, 특정 key 에 접근하기 위해서는 leaf node까지 가야 한다. 그리고 leaf node끼리는 Linked list로 연결되어 있는데, 이를 통해 효율적인 순차 검색, 부등호 연산이 가능해지게 된다.

참고

  • 코딩애플, index가 뭔지 설명해보세요, https://www.youtube.com/watch?v=iNvYsGKelYs
This post is licensed under CC BY 4.0 by the author.

© . Some rights reserved.

Using the Jekyll theme Chirpy