[데이터베이스] INDEX

Dev_Sanizzang·2023년 5월 20일
0

데이터베이스

목록 보기
5/5

📕 개요

오늘은 예전부터 궁금해 했던 데이터베이스 INDEX에 대해 알아보고자 한다.

이 글은 우아한 Tech에서 진행한 10분 테코톡을 시청한 뒤 정리한 내용을 적을 것이다. 테코톡 짱👍

💡 [10분 테코톡] 라라, 제로의 데이터베이스 인덱스

인덱스란?

사전적 정의로는 색인이다.

  • 색인: 쉽게 찾아볼 수 있도록 일정한 순서에 따라 놓은 목록

예를 들어 자바의 정석 책의 다형성 파트를 찾아보고 싶을때 ㄱㄴㄷ 순으로 정렬된 찾아보기 페이지에 가서 ㄷ-ㄹ에 가서 다형성을 찾을 수 있다.

이처럼 원하는 값을 빠르게 찾는다는 것에 초점이 맞춰져 있다.

이를 데이터베이스에도 적용하면 어떻게 될까?

SELECT, INSERT, UPDATE, DELETE 중 '찾는다'에 해당하는 SELECT에 활용할 수 있다.

데이터베이스 인덱스란?

현재 이름, 성별, 이메일 등 백만 건 이상 데이터가 인덱스 기준이 하나도 잡혀있지 않을 때 이메일을 통해 조회를 해본다고 가정한다. 이때 전체 데이터에서 순차적으로 확인하기 때문에 매우 느릴 것이다.
-> 현재 데이터는 기준 없이 저장된 상태이기 때문
-> 만약에 데이터가 특정 기준으로 정렬되어 있다면 검색을 빠르게 할 수 있을 것이다.

이메일을 데이터베이스 인덱스로 정한 경우?

이의 경우 현재 데이터는 이메일로 정렬된 백만건 이상의 데이터로 바뀔 것이다.
여기서 다시 이메일을 통해 조회하게 되면 속도가 매우 빨라질 것이다.

SELECT * FROM member WHERE email = 'asebn121@gmail.com'
  1. 인덱스가 적용된 대상을(email로 정렬된 데이터)
  2. WHERE 절을 통해 검색
SELECT * FROM member
  1. WHERE 절을 통해 검색 X
  2. 인덱스가 사용되지 않음

💡 인덱스는 데이터베이스 테이블에 대한 검색 성능을 향상시키는 자료 구조이며 WHERE 절 등을 통해 활용된다.

인덱스의 특징

  1. 인덱스는 항상 최신의 정렬상태를 유지
  2. 인덱스도 하나의 데이터베이스 객체
  3. 데이터베이스 크기의 약 10% 정도의 저장공간 필요

인덱스 알고리즘

페이지

데이터가 저장되는 단위(16 Kbyte -> MySQL 기준(데이터베이스 환경마다 다를 수 있다))

Full Table Scan

  1. 순차적으로 접근
  2. 접근 비용 감소

💡 Full Table Scan 사용?
1. 적용 가능한 인덱스가 없는 경우
2. 인덱스 처리 범위가 넓은 경우
3. 크기가 작은 테이블에 엑세스 하는 경우

B-Tree

Binary Search Tree (이진 탐색 트리)

이진탐색과 연결리스트의 장점이 합쳐져 만들어진 자료구조

균형있는 이진탐색트리의 경우 검색 시간복잡도는 O(log n)이다.
하지만 균형 없는 이진탐색 트리의 시간복잡도는 최악의 경우 O(n)이다.
이는 이진탐색트리의 장점을 살렸다고 볼 수 없다.

이러한 이진탐색트리의 단점을 극복하기 위해서 여러 자료구조가 나왔고 그 중 하나가 "B-Tree"이다.

B-Tree(Balanced-Tree)

  1. 트리 높이가 같음
  2. 자식 노드를 2개 이상 가질 수 있음
  3. 기본 데이터베이스 인덱스 구조

최상단에는 루트 페이지가 오며
브랜치 페이지는 루트 페이지와 리프 페이지 사이에 여러 개가 올 수 있다.
최하단에는 리프 페이지가 온다.

이를 통해 SELECT의 성능이 향상되는 것을 알 수 있게 되었다.

❗ 그렇다면 INSERT, UPDATE, DELETE는 어떻게 될까?

페이지 분할

  1. 페이지에 새로운 데이터를 추가할 여유공간이 없어 페이지에 변화가 발생
  2. DB가 느려지고 성능에 영향을 준다.

DELETE

인덱스의 데이터를 실제로 지우지 않고 사용안함 표시를 한다.

UPDATE

  1. DELELTE (기존 값 사용안함 표시)
  2. INSERT (변경된 값 삽입)

❗ UPDATE, DELETE의 경우도 WHERE 절을 사용할 때 빨라질까?

WHERE 절로 처리할 대상을 찾기 위한 조회 성능은 향상된다.

  • 사용하지 않는 인덱스가 적용되었다면 불필요한 처리량 증가
  • 사용안함 표시로 페이지 낭비 및 인덱스 조각화 심해짐

인덱스 종류

클러스터 (Cluster)

  1. 무리, 군집
  2. 무리를 이루다

데이터베이스에서 클러스터링이란?

클러스터링

실제 데이터와 무리를 이름

클러스터링 인덱스

실제 데이터와 같은 무리의 인덱스

논-클러스터링

실제 데이터와 무리를 이루지 않음
-> 실제 데이터가 정렬된 사전과 같은 역할을 하는게 클러스터링 인덱스

논-클러스터링 인덱스

실제 데이터와 다른 무리의 별도의 인덱스
-> 앞에서 설명했던 책 내용을 찾기 위해 책 뒤에 별도로 존재했던 찾아보기 페이지와 같은 역할을 하는게 논-클러스터링 인덱스

😲 놀라운 사실은 우리도 모르는 새에 데이터베이스 인덱스를 사용하고 있었다.

CREATE TABLE member (
	id    int           primary key,
    name  varchar(255),
    email varchar(255)  unique,
);

위와 같이 테이블만 생성을 해도 자동으로 인덱스가 생성이 된다.
-> PK와 UNIQUE 제약 조건 때문

한 컬럼에 PK를 적용하면 클러스터링 인덱스가 자동으로 생성되게 된다.

그리고 한 컬럼에 unique 제약조건을 걸게 되면 논-클러스터링 인덱스가 자동으로 생성이 된다.

클러스터링 인덱스 추가 방법

방법 1

ALTER TABLE member
ADD CONSTRAINT pk_id PRIMARY KEY (id);
  • PK

방법 2

ALTER TABLE member MODIFY COLUMN id int NOT NULL;
ALTER TABLE member ADD CONSTRAINT nuq_id UNIQUE (id);
  • NOT NULL + UNIQUE

  • 1000, 1001과 같은 숫자는 데이터 페이지의 주소를 의미한다.
  • 데이터 페이지는 실제 데이터가 저장되는 곳을 의미한다.
    (모든 column에 대한 실제 데이터를 다 담고 있는 페이지)

클러스터링 인덱스 특징

  1. 실제 데이터 자체가 정렬
  2. 테이블당 1개만 존재 가능
  3. 리프 페이지가 데이터 페이지
  4. 아래의 제약조건 시 자동 생성
  • primary key (우선순위)
  • unique + not null

논-클러스터링 인덱스 추가 방법

방법 1

ALTER TABLE member
ADD CONSTRAINT unq_name UNIQUE (name);
  • UNIQUE

방법 2

CREATE UNIQUE INDEX unq_inx_name 
ON member (name);
  • UNIQUE INDEX 생성

방법 3

CREATE INDEX idx_name
ON member (name);
  • INDEX 생성

"도리" 옆에 있는 숫자 (1002 + #3)에서 1002는 실제 데이터 페이지의 주소를 의미하고 옆에 3은 1002 페이지의 세 번째에 "도리"에 대한 데이터가 존재한다는 주소를 의미한다.

논-클러스터링 인덱스 특징

  1. 실제 데이터 페이지는 그대로
  2. 별도의 인덱스 페이지 생성 -> 추가 공간 필요
  3. 테이블당 여러 개 존재
  4. 리프 페이지에 실제 데이터 페이지 주소를 담고 있음
  5. unique 제약조건 적용시 자동 생성
  6. 직접 index 생성시 논-클러스터링 인덱스 생성

❗ 클러스터링 인덱스와 논-클러스터링 인덱스를 함께 적용하면?

데이터 페이지의 주소 값이 아닌 클러스터링 인덱스가 적용된 id 컬럼의 값이 적용되어 있다. "도리"의 id는 6이기 때문에 6을 담고 있고 "라라"는 12를 담고 있다.

❗ 왜 데이터 페이지의 주소가 들어있지 않을까?

만약 id가 3인 파랑의 데이터가 추가로 삽입됐다고 해보자
그러면 id를 기준으로 정렬되야하기 때문에 "파랑"의 데이터는 "제로" 밑에 들어와야 한다. "호호"와 "스컬은" 4, 5번이기 때문에 페이지 분할이 발생하게 된다.

그렇게 되면 name 인덱스 페이지에서 "스컬"과 "호호"의 주소는 변경되어야 한다.
데이터가 추가되거나 삭제될 때마다 이 인덱스 페이지의 주소들을 계속해서 변경해야 하는 영향을 주기 때문에 id가 직접 변경되지 않는 한 인덱스 페이지에 영향을 주지 않도록 구성하고 있다.

인덱스 적용 기준

어떤 컬럼에 인덱스를 적용해야 할까?

카디널리티

사전적 의미: 그룹 내 요소의 개수

카디널리티(그룹 내 요수의 개수)가 높은것
= 중복도가 낮은 것

💡 사용하면 좋은 경우
1. 카디널리티가 높은 (중복도가 낮은) 컬럼
2. WHERE, JOIN, ORDER BY 절에 자주 사용되는 컬럼
- 인덱스는 추가 공간이 필요로 된다
- 조건 절이 없다면 인덱스가 사용되지 않는다.
3. INSERT / UPDATE / DELETE 가 자주 발생하지 않는 컬럼
4. 규모가 작지 않은 테이블

인덱스 사용시 주의사항

  1. 잘 활용되지 않는 인덱스는 과감히 제거하자
    • WHERE 절에 사용되더라도 자주 사용해야 가치가 있다
    • 불필요한 인덱스로 성능저하가 발생할 수 있다
  2. 데이터 중복도가 높은 컬럼은 인덱스 효과가 적다
  3. 자주 사용되더라도 INSERT / UPDATE / DELETE가 자주 일어나는지 고려해야 한다
    • 일반적인 웹 서비스와 같은 온라인 트랜잭션 환경에서 쓰기와 읽기 비율은 2:8 또는 1:9이다
    • 조금 느린 쓰기를 감수하고 빠른 읽기를 선택하는 것도 하나의 방법이다

🚪 마무리

오늘은 인덱스에 대해서 알아봤다. 테코톡 덕분에 짧은 시간 내에 인덱스에 대해 이해할 수 있었던 것 같다. 나중에 데이터베이스 성능이 안나오면 인덱스를 적용해 볼 수 있을 것 같다!

profile
기록을 통해 성장합니다.

0개의 댓글