인덱스: 두 판 사이의 차이

기술노트
(CS 용어 정리 - 인덱스 추가)
(Gemini 벌크 업로더로 자동 업로드)
 
(같은 사용자의 중간 판 하나는 보이지 않습니다)
1번째 줄: 1번째 줄:
== 인덱스 ==
== 🔑 인덱스 (Index) ==


=== 인덱스의 필요성 ===
데이터베이스의 '''인덱스'''는 테이블의 검색 속도를 향상시키기 위한 자료구조입니다. 책의 맨 뒤에 있는 '찾아보기(색인)'와 같은 역할을 합니다. 특정 내용을 찾기 위해 책의 모든 페이지를 다 뒤지는 대신, 찾아보기를 통해 원하는 내용이 있는 페이지를 바로 찾을 수 있듯이, 인덱스는 데이터베이스가 특정 데이터를 빠르게 찾을 수 있도록 도와줍니다.


* 인덱스는 데이터를 빠르게 찾을 수 있는 하나의 장치다.
----
* 인덱스를 설정하면 테이블 안에 내가 찾고자 하는 데이터를 빠르게 찾을 수 있다.


=== B-트리 ===
=== 🤔 인덱스는 왜 필요한가? ===


인덱스는 보통 B-트리라는 자료 구조로 이루어져 있다. 이는 루트 노드, 리프 노드, 그리고 루트 노드와 리프 노드 사이에 있는 브랜치 노드로 나뉜다.
인덱스가 없는 테이블에서 특정 데이터를 찾으려면, 데이터베이스는 테이블의 모든 행을 처음부터 끝까지 순차적으로 검색해야 합니다. 이를 '''풀 테이블 스캔(Full Table Scan)'''이라고 합니다. 데이터의 양이 적을 때는 문제가 없지만, 수백만, 수천만 건의 데이터가 있는 테이블에서는 풀 테이블 스캔이 매우 느리고 시스템에 큰 부하를 줍니다.


루트 노드와 리프 노드를 기반으로 설명하면 다음과 같다.
인덱스는 데이터와 해당 데이터의 위치(주소)를 키-값 쌍으로 미리 정렬하여 저장해 둠으로써, 풀 테이블 스캔을 피하고 데이터 검색 속도를 획기적으로 향상시킵니다.


![인덱싱](https://user-images.githubusercontent.com/97720335/218648724-e91ac187-8e97-4c56-9bcd-f1ce11190884.jpeg)
----


예를 들어 E를 찾는다고 하면 전체 테이블을 탐색하는 것이 아니라 E가 있을 법한 리프 노드로 들어가서 E를 탐색하면 쉽게 찾을 수 있다.이 자료 구조 없이 E를 탐색하고자 하면 A, B, C, D, E 다섯 번을 탐색해야 하지만, 이렇게 노드들로 나누면 두 번만에 리프 노드에서 찾을 수 있다.
=== ⚙️ 인덱스의 동작과 자료구조 ===


==== 인덱스가 효율적인 이유와 대수확장성 ====
대부분의 RDBMS는 인덱스를 구현하기 위해 '''B-Tree(Balanced Tree)''' 자료구조를 사용합니다. B-Tree는 항상 균형을 유지하도록 설계된 트리 구조로, 어떤 값을 찾더라도 항상 비슷한 시간 복잡도(O(log N))로 데이터를 빠르게 검색할 수 있습니다.


인덱스가 효율적인 이유는 효율적인 단계를 거쳐 모든 요소에 접근할 수 있는 균형 잡힌 트리 구조와 트리 깊이의 대수확장성 때문이다.
* '''SELECT''' 쿼리의 `WHERE` 절이나 `JOIN` 조건에 사용되는 컬럼에 인덱스를 생성하면 성능이 크게 향상됩니다.


`대수확장성` : 트리 깊이가 리프 노드 수에 비해 매우 느리게 성장하는 것을 의미한다. 기본적으로 인덱스가 한 깊이씩 증가할 때마다 최대 인덱스 항목의 수는 4배씩 증가한다.
----


=== 인덱스 만드는 방법 ===
=== ⚖️ 인덱스의 장단점 ===


인덱스를 만드는 방법은 데이터베이스마다 다르며 MySQL과 MongoDB를 기준으로 설명한다.
* '''장점''' :
> * 데이터 검색(SELECT) 속도가 매우 빨라집니다.


==== MySQL ====
* '''단점''' :
> * '''추가 저장 공간''': 인덱스 자체도 공간을 차지하므로, 테이블 크기의 약 10% 정도의 추가 공간이 필요합니다.
> * '''느린 CUD(Create, Update, Delete) 속도''': 데이터를 추가, 수정, 삭제할 때마다 인덱스 테이블도 함께 업데이트해야 하므로, 쓰기 작업의 성능이 저하됩니다.
> * '''무분별한 사용의 위험''': 너무 많은 인덱스는 오히려 성능을 저하시킬 수 있습니다.


MySQL의 경우 클러스터형 인덱스와 세컨더리 인덱스가 있으며, 클러스터형 인덱스는 테이블당 하나를 설정할 수 있다. `primary key` 옵션으로 기본키로 만들면 클러스터형 인덱스를 생성할 수 있고, 기본키로 만들지 않고 `unique not null` 옵션을 붙이면 클러스터형 인덱스로 만들 수 있다.
----


`create index...` 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있다. 하나의 인덱스만 생성할 것이라면 클러스터형 인덱스를 만드는 것이 세컨더리 인덱스를 만드는 것보다 성능이 좋다.
=== 💡 정보처리기사 핵심 Point ===


세컨더리 인덱스는 보조 인덱스로 여러 개의 필드 값을 기반으로 쿼리를 많이 보낼 때 생성해야 하는 인덱스다.
* 인덱스는 '''읽기 작업은 빠르게, 쓰기 작업은 느리게''' 만듭니다.
 
* 따라서, 데이터의 변경(INSERT, UPDATE, DELETE)은 적고 검색은 빈번한 컬럼에 인덱스를 생성하는 것이 가장 효과적입니다.
==== MongoDB ====
* 카디널리티(Cardinality), 즉 중복도가 낮은(고유한 값이 많은) 컬럼에 인덱스를 생성해야 효율이 좋습니다. (예: `주민등록번호` O, `성별` X)
 
* SQL 쿼리의 '''실행 계획(Execution Plan)'''을 분석하여, 쿼리가 인덱스를 잘 활용하고 있는지 주기적으로 확인하고 최적화하는 습관이 중요합니다.
MongoDB의 경우 도큐먼드를 만들면 자동으로 ObjectID가 형성되며, 해당 키가 기본키로 설정된다. 그리고 세컨더리키도 부가적으로 실행해서 기본키와 세컨더리키를 같이 쓰는 복합 인덱스를 설정할 수 있다.
 
=== 인덱스 최적화 기법 ===
 
인덱스 최적화 기법은 데이터베이스마다 조금씩 다르지만 기본적인 골조는 똑같기 때문에 특정 데이터베이스를 기준으로 설명해도 무방하다. 이 책에서는 MongoDB를 기반으로 인덱스 최적화 기법을 설명한다.
 
<br>
 
==== 1. 인덱스는 비용이다. ====
 
* 먼저 인덱스는 두 번 탐색하도록 강요한다. 인덱스 리스트, 그 다음 컬렉션 순으로 탐색하기 때문이며, 관련 읽기 비용이 들게 된다.
* 컬렉션이 수정되었을 때 인덱스도 수정되어야 한다. 책의 본문이 수정되었을 때 목차나 찾아보기도 수정하는 듯 해야한다. 이때 B-트리의 높이를 균형 있게 조절하는 비용도 들고, 데이터를 효율적인 조회할 수 있도록 분산시키는 비용도 들게 된다.
* 쿼리에 있는 필드에 인덱스를 무작정 다 설정하는 것은 답이 아니다. 또한, 컬렉션에서 가져와야 하는 양이 많을수록 인덱스를 사용하는 것이 비효율적이다.
 
==== 2. 항상 테스팅하라 ====
 
인덱스 최적화 기법은 서비스 특징에 따라 달라진다. 서비스에서 사용하는 객체의 깊이, 테이블의 양 등이 다르기 때문이다. 그렇기 때문에 항상 테스팅하는 것이 중요하다. `explain()` 함수를 통해 인덱스를 만들고 쿼리를 보낸 이후에 테스팅을 하며 걸리는 시간을 최소화해야 한다.
 
'''MySQL에서는 다음과 같은 코드로 테스팅을 수행한다.'''
 
<syntaxhighlight>sql
EXPLAIN
SELECT * FROM t1
JOIN t2 ON t1.c1 = t2.c1
</syntaxhighlight>
 
==== 복합 인덱스는 같음, 정렬, 다중 값, 카디널리티 순이다 ====
 
보통 여러 필드를 기반으로 죄회를 할 때 복합 인덱스를 생성하는데, 이 인덱스를 생성할 때는 순서가 있고 생성 순서에 따라 인덱스 성능이 달라진다. 같음, 정렬, 다중 값, 카디널리티 순으로 생성해야 한다.
 
1. 어떠한 값과 같음을 비교하는 == 이나 equal이라는 쿼리가 있다면 제일 먼저 인덱스로 설정한다.
2. 정렬에 쓰는 필드라면 그 다음 인덱스로 설정한다.
3. 다중 값을 출력해야 하는 필드, 즉 쿼리 자체가 > 이거나 < 등 많은 값을 출력해야 하는 쿼리에 쓰는 필드라면 나중에 인덱스를 설정한다.
4. 유니크한 값의 정도를 `카디널리티` 라고 한다. 이 카디널리티가 높은 순서를 기반으로 인덱스를 생성해야 한다.예를 들어 age와 email이 있다고 가정했을 때, email이 더 높아 email이라는 필드에 대한 인덱스를 먼저 생서앻야 한다.

2025년 9월 6일 (토) 05:54 기준 최신판

🔑 인덱스 (Index)

데이터베이스의 인덱스는 테이블의 검색 속도를 향상시키기 위한 자료구조입니다. 책의 맨 뒤에 있는 '찾아보기(색인)'와 같은 역할을 합니다. 특정 내용을 찾기 위해 책의 모든 페이지를 다 뒤지는 대신, 찾아보기를 통해 원하는 내용이 있는 페이지를 바로 찾을 수 있듯이, 인덱스는 데이터베이스가 특정 데이터를 빠르게 찾을 수 있도록 도와줍니다.


🤔 인덱스는 왜 필요한가?

인덱스가 없는 테이블에서 특정 데이터를 찾으려면, 데이터베이스는 테이블의 모든 행을 처음부터 끝까지 순차적으로 검색해야 합니다. 이를 풀 테이블 스캔(Full Table Scan)이라고 합니다. 데이터의 양이 적을 때는 문제가 없지만, 수백만, 수천만 건의 데이터가 있는 테이블에서는 풀 테이블 스캔이 매우 느리고 시스템에 큰 부하를 줍니다.

인덱스는 데이터와 해당 데이터의 위치(주소)를 키-값 쌍으로 미리 정렬하여 저장해 둠으로써, 풀 테이블 스캔을 피하고 데이터 검색 속도를 획기적으로 향상시킵니다.


⚙️ 인덱스의 동작과 자료구조

대부분의 RDBMS는 인덱스를 구현하기 위해 B-Tree(Balanced Tree) 자료구조를 사용합니다. B-Tree는 항상 균형을 유지하도록 설계된 트리 구조로, 어떤 값을 찾더라도 항상 비슷한 시간 복잡도(O(log N))로 데이터를 빠르게 검색할 수 있습니다.

  • SELECT 쿼리의 `WHERE` 절이나 `JOIN` 조건에 사용되는 컬럼에 인덱스를 생성하면 성능이 크게 향상됩니다.

⚖️ 인덱스의 장단점

  • 장점 :

> * 데이터 검색(SELECT) 속도가 매우 빨라집니다.

  • 단점 :

> * 추가 저장 공간: 인덱스 자체도 공간을 차지하므로, 테이블 크기의 약 10% 정도의 추가 공간이 필요합니다. > * 느린 CUD(Create, Update, Delete) 속도: 데이터를 추가, 수정, 삭제할 때마다 인덱스 테이블도 함께 업데이트해야 하므로, 쓰기 작업의 성능이 저하됩니다. > * 무분별한 사용의 위험: 너무 많은 인덱스는 오히려 성능을 저하시킬 수 있습니다.


💡 정보처리기사 핵심 Point

  • 인덱스는 읽기 작업은 빠르게, 쓰기 작업은 느리게 만듭니다.
  • 따라서, 데이터의 변경(INSERT, UPDATE, DELETE)은 적고 검색은 빈번한 컬럼에 인덱스를 생성하는 것이 가장 효과적입니다.
  • 카디널리티(Cardinality), 즉 중복도가 낮은(고유한 값이 많은) 컬럼에 인덱스를 생성해야 효율이 좋습니다. (예: `주민등록번호` O, `성별` X)
  • SQL 쿼리의 실행 계획(Execution Plan)을 분석하여, 쿼리가 인덱스를 잘 활용하고 있는지 주기적으로 확인하고 최적화하는 습관이 중요합니다.