[Database] Index

jaylight·2021년 3월 10일
0

내용 출처
1. [10분 테크톡] 🏫안돌의 INDEX

Index

Index: (검색을 위해) 특정 규칙에 의해 부여된 임의의 대상을 가리키는 키

DB에서 자주 접근하여 사용하는 테이블을 메모리에 올려서 사용할 경우, 사용자의 데이터 요청에 빠르게 대응할 수 있는데 만약 이와 같이 데이터를 메모리에 올려두지 않는다면 Full Table Scan을 수행해야 하며 이는 데이터 용량이 커질수록 효율성이 반비례하여 낮아짐

이와 같은 Full Scan을 막기 위해서 Index를 만들며, Index를 메모리에 저장해 둠

Index의 유형

Clustered Index

  • 왼쪽이 Index, 오른쪽 데이터라고 볼 때, 특정 기준에 따라 위와 같이 정렬이 되어있을 수 있음
  • 따라서 특정 기준에 대한 범위 검색을 할 때 매우 효율적으로 처리 가능함
  • 하지만 위와 같이 새로운 데이터가 추가되는 상황이라면? 아래쪽 데이터를 하나씩 밀고 새롭게 2번을 인천에 부여해야함
  • 만약 10,000,000개의 데이터가 있을 때, 중간에 데이터가 추가된다면 매우 비효율적이 상황이 발생

[정리]

  • PK 개념과 유사
  • 한 테이블에 한 개의 Clustered Index를 부여
  • 범위 검색에 있어 효율적이지만, 존재하는 PK 사이에 추가적인 데이터 INSERT할 경우 매우 비효율적
  • 보통은 Auto_Increment를 사용하는데 위와같이 INSERT에 따른 비효율성 때문

Non-Clustered Index

  • 참조하는 인덱스가 바로 데이터와 연결되어있지 않고, 다른 인덱스와 연결되어 있음
  • 또 다른 인덱스를 통해 데이터를 간접적으로 참조 가능: 약한 참조 관계

[정리]

  • 관용적인 Index 개념과 유사
  • 한 테이블에 여러 차원에서 Index 부여가 가능
  • 추가적인 저장공간이 필요 (약 10% 정도 추가됨)
  • INSERT 시 인덱싱을 생성하는 작업이 필요 (Clustered 처럼 열을 전부 뒤집는 작업은 아니다.)

Index의 구조와 원리

Inex는 B-Tree 자료 구조를 활용하여 Index를 구성한다. B-Tree는 자식 노드가 최대 2개인 이진트리의 변형으로 자식노드가 2개 이상인 Tree를 뜻한다.

B-Tree가 Database에서 운용되는 방식은 수직적 탐색과 수평적 탐색이 동시에 이루어지며, 수직적으로 조건을 만족하는 첫 번째 Record를 찾아 선택하고 Leaf Node에서 수평적으로 조건을 만족하는 Record를 찾는다.

위 상황에서 5번 멤버 번호를 가진 데이터를 찾고자 할 때,

  1. Root Table에서 team01의 3번 멤버가 가리키는 Child Table인 2로 들어간다.
  2. Child Table 2에서 3과 10으로 분기되는 상황에서 찾고자 하는 목표인 5가 시작되기 전 번호인 3번 번호의 Child Table 10으로 들어간다.
  3. Child Table 10에서 멤버 번호 5를 찾아서 말단 Row 주소를 Disk에서 조회한다.

InnoDb Storage Engine은 디스크에 데이터를 저장하는 가장 기본 단위를 페이지 혹은 블록으로 하며, 이는 디스크의 I/O 작업의 최소 단위가 되므로 인덱스 또한 페이지 단위로 관리된다고 이해할 수 있다.

Index의 활용

Index를 언제 사용해야하는가?

Index를 활용함으로써 효율성을 가장 극대화 시킬 수 있는 상황은 SELECT(조회) 기능을 수행할 때이다. 반면 INSERT, UPDATE, DELETE에서는 INDEX 작업을 하는 것이 오히려 성능을 저하할 수 있는데 이유는 아래와 같다.

  • INSERT: 정렬이 된 상태로 INDEX가 저장된 상태에서 INSERT를 함으로써 특정 위치에 데이터를 넣고 기존 데이터를 뒤로 밀어남으로써 작업양이 증대
  • DELETE: INDEX의 데이터를 실제 지우지 않고, 사용 안함으로 표시하기 때문에 공간 상 낭비가 발생하게 됨
  • UPDATE: INDEX에는 UPDATE 개념이 없기 때문에 DELETE을 하고 INSERT를 함으로써 성능 저하가 발생

어디에 Index를 걸 것인가?: Cardinality

Cardinality: the number of elements in a set or group

특정 칼럼에 대해 Index를 했을 때, 그 상대적인 효과성을 평가할 수 있는 지표로서, 동일 칼럼 내에 중복된 항목(데이터)이 많을 수록 카디널리티가 낮아지고, 고유한 값일 수록 카디널리티가 높아진다.

성별주민번호 중 어디에 인덱스를 걸어야 할까?

  • 결론적으로 성별에 비해 주민번호가 Cardinality가 더 높으며, 주민번호에 인덱스를 거는 것이 더욱 효율적이다.
  • 이름 = 펭수, 성별 = 남성, 나이 = 10살, 주민번호 = 100808-3111111 데이터를 찾는다고 할 때,
  • 주민번호를 기준으로 찾는 것이 가장 효율적이고 정확하게 원하는 값을 식별할 수 있음

Cardinality를 가장 직관적으로 이해하는 방법 중 하나는 해당 칼럼의 값을 전부 뽑아 set() 메서드에 넣어 고유한 값만 남긴다고 생각해보면 쉽다. 1,000개의 유저 정보가 담긴 테이블에서 성별칼럼의 데이터를 전부 뽑아서 set() 에 넣는다면 (특수한 경우가 아니라면) 남성, 여성 두가지 항목만 남는다. 하지만 주민번호 칼럼의 경우 같은 과정을 거쳤을 때 1,000개의 항목이 그대로 남게 될 것이다. 따라서 주민번호 set에 담긴 개별 요소의 수 (the number of elements in a set or group)가 더 많다고 이해하면 되는 것이다.

따라서, 어떤 컬럼에 대해 인덱스를 걸지 결정할 때, 해당 컬럼에 인덱스를 걸었을 때 얼마나 손쉽게 개별 데이터 식별이 가능한지를 고려해야하며, 이 때 활용할 수 있는 개념이 Cardinality인 것이다.

0개의 댓글