개발자 기술면접 꼬리물기 질문
  • Welcome
  • 01 Java
    • 01-01. Generic
    • 01-02. Garbage Collection
    • 01-03. 자료형과 객체 비교
    • 01-04. 힙(Heap)과 메모리(Memory)
    • 01-05. Java 버전과 JDK / JRE
    • 01-06. 스레드(Thread)
    • 01-07. 예외(Throwable)
    • 01-08. Call By Value와 Call By Reference
    • 01-09. String, equals, StringBuffer
    • Thread와 비동기
  • 02 Spring
    • 02-01. Spring 동작 방식
    • 02-02. 인증(Authentication)과 인가(Authorization)
    • @Autowired, @RequiredArgsConstructor
    • 트랜잭션(Transaction)
    • QueryDSL과 SQL Injection
    • SecurityContextHolder
    • @EqualsAndHashCode
  • 03 DATABASE
    • 03-01. Join
    • 03-02. Index
    • 정규화 (Normalization)
    • 파티셔닝과 샤딩(Partitioning & Sharding)
    • 트랜잭션(Transaction)과 락(Lock)
    • 덤프(Dump)
    • Redis
    • 격리 수준(MySQL)
  • 04 Algorithms & Data Structures
    • 04-01. Set
    • 04-02. 정렬
    • 04-03. 우선순위 큐 (Priority Queue)
    • DFS와 BFS
    • 힙(Heap) 자료구조
    • 스택(Stack)과 큐(Queue)
    • 암호화 알고리즘
    • LinkedList
    • 자료구조 - 해시 테이블(HashTable)
    • 자료구조 - ConcurrentHashMap
  • 05 NETWORK
    • 05-01 Proxy Server
    • 05-02 Http 프로토콜
    • 전송 계층 (Transport Layer)
    • 네트워크 계층 (Network Layer)
    • Http와 Https
    • IP(Internet Protocol)
    • 소켓(Socket)
    • 로드 밸런싱(Load Balancing)
  • 06 WEB
    • 06-01 CORS 정책
    • 동시성 제어
    • N+1 문제
    • 웹 브라우저 동작원리
    • URI, URL, URN
    • 채팅 아키텍처 설계
  • 디자인 패턴
    • 전략 패턴 (Strategy Pattern)
    • 싱글톤 패턴 (Singleton Pattern)
    • 템플릿 메서드 패턴과 전략 패턴
    • 데코레이터 패턴 (Decorator pattern)
  • 개발자
    • 개발 방법론 TDD
  • 운영체제
    • JIT & AOT 컴파일
    • 컨텍스트 스위칭(Context Switching)
    • 프로세스와 스레드
    • 싱글 스레드와 멀티 스레드
  • 코딩테스트
    • Stack / Queue (스택 / 큐)
    • Heap(우선 순위 큐)
    • DP(동적 계획법)
    • DFS(깊이 우선 탐색)
    • BFS(너비 우선 탐색)
    • Greedy(그리디 알고리즘)
    • 해시(Hash)
    • 투 포인터 알고리즘
    • Shortest path
    • 수학적 사고
Powered by GitBook
On this page
  • Q. 데이터베이스 Index에 대해서 설명해주세요.
  • Q. Index를 설정하면 내부적으로 어떻게 동작하나요?
  • Q. B-Tree 구조는 어떻게 되며 인덱스를 사용할 때와 사용하지 않을 때 시간복잡도 차이는 어떻게 되나요?
  • Q. LIKE 검색을 할 때, 인덱스가 항상 적용될까요?
  • Q. 클러스터드 인덱스와 넌클러스터드 인덱스는 어떻게 다르며, 언제 사용하나요?
  1. 03 DATABASE

03-02. Index

Previous03-01. JoinNext정규화 (Normalization)

Last updated 24 days ago

Q. 데이터베이스 Index에 대해서 설명해주세요.

데이터베이스 인덱스는 테이블의 특정 컬럼에 대한 검색 성능을 최적화하기 위해 설계된 데이터 구조입니다.

마치 책의 색인처럼, 데이터베이스가 방대한 데이터 속에서 원하는 레코드를 빠르게 찾아낼 수 있도록 돕습니다.

인덱스는 선택된 컬럼의 값을 정렬된 형태로 저장하며, 이를 통해 전체 테이블을 순차적으로 스캔(Full Table Scan)하지 않고도 필요한 데이터를 효율적으로 조회할 수 있습니다.

예를 들어, 수백만 행의 고객 테이블에서 특정 이메일 주소를 찾을 때, 인덱스가 없으면 모든 행을 확인해야 하지만, 인덱스가 있다면 단 몇 번의 탐색으로 결과를 반환합니다.

하지만 인덱스는 장점만 있는 것이 아닙니다.

데이터 삽입(INSERT), 수정(UPDATE), 삭제(DELETE) 작업이 발생할 때마다 인덱스도 함께 갱신되므로 쓰기 성능에 부담을 줄 수 있습니다.

또한, 인덱스는 별도의 저장 공간을 차지하므로 디스크 사용량이 증가합니다.

따라서 실무에서는 적절한 인덱스를 설계해야 합니다.

예를 들어, 읽기 중심의 분석용 데이터베이스라면 인덱스를 적극 활용하고, 쓰기 중심의 트랜잭션 시스템이라면 최소화하는 식으로 전략을 세웁니다.

Q. Index를 설정하면 내부적으로 어떻게 동작하나요?

인덱스를 설정하면 데이터베이스는 해당 컬럼을 기반으로 B-Tree 또는 변형인 B+Tree 데이터 구조를 생성합니다.

B-Tree는 키 값과 데이터 위치를 가리키는 포인터로 구성된 노드들이 계층적으로 연결된 트리입니다.

데이터베이스는 이 구조를 활용해 검색 요청이 들어오면 루트 노드에서 시작해 키 값을 비교하며 하위 노드로 이동, 최종적으로 원하는 데이터의 물리적 위치를 찾아냅니다.

예를 들어, WHERE id = 100 쿼리가 실행되면 B-Tree는 'id' 값을 기준으로 트리를 탐색해 해당 레코드의 주소를 즉시 반환합니다.

B-Tree 외에도 데이터베이스 엔진에 따라 해시 테이블이나 비트맵 같은 다른 구조를 사용할 수 있지만, B-Tree는 범위 검색과 정렬된 데이터 접근에 강점이 있어 가장 널리 사용됩니다.

Q. B-Tree 구조는 어떻게 되며 인덱스를 사용할 때와 사용하지 않을 때 시간복잡도 차이는 어떻게 되나요?

B-Tree는 자체적으로 균형을 유지하는 다진 트리(multiway tree) 로, 각 노드가 여러 개의 키와 해당 키에 대응하는 자식 노드 포인터를 가집니다.

루트 노드에서 시작해 리프 노드까지 이어지며, 모든 리프 노드는 동일한 깊이를 유지합니다. 이 구조는 디스크 기반 데이터베이스에 최적화되어 있는데, 노드당 많은 키를 저장해 트리의 깊이를 얕게 유지하고, 디스크 I/O를 최소화합니다.

이제 시간복잡도를 살펴보면

  • 인덱스 사용 시: B-Tree의 탐색은 이진 검색과 유사하지만, 다중 키 덕분에 시간복잡도는 O(logn) 입니다. 여기서 n은 레코드 수이며, 로그의 밑은 B-Tree의 차수(order) 또는 한 노드가 가질 수 있는 최대 자식 노드의 수에 따라 달라집니다.

  • 인덱스 미사용 시: 테이블 전체를 순차적으로 스캔해야 하므로 시간복잡도는 O(n) 입니다. 데이터가 클수록 성능 차이가 극명해집니다. 예를 들어, 1,000,000행에서 특정 값을 찾을 때 인덱스 없이 최대 1,000,000번 비교해야 하지만, B-Tree 인덱스라면 일반적으로 20번 이내에 완료됩니다.

B-Tree의 변형인 B+Tree는 리프 노드에만 데이터를 저장하고, 리프 노드 간 링크를 추가해 범위 검색 성능을 더 개선합니다. MySQL의 InnoDB 엔진은 B+Tree를 기본으로 사용합니다.

Q. LIKE 검색을 할 때, 인덱스가 항상 적용될까요?

B-Tree 인덱스는 문자열의 접두사(왼쪽부터 시작)를 기준으로 정렬되므로, LIKE 'abc%' 같은 접두사 검색에서는 효과적으로 동작합니다.

예를 들어, WHERE name LIKE 'John%'는 'John'으로 시작하는 모든 이름을 빠르게 찾습니다.

그러나 와일드카드(% 또는 _)가 문자열의 시작 부분에 사용되는 접미사 검색(LIKE '%son')이나 중간 검색(LIKE '%oh%')에서는 정렬 순서를 활용할 수 없어 인덱스가 적용되지 않거나 매우 비효율적입니다.

이 경우 데이터베이스는 Full Table Scan을 수행하며, 성능이 O(n)에 가까워집니다.

이를 해결하려면 특수 인덱스를 사용해야 합니다:

  • Full-Text Index: 단어 단위로 텍스트를 분리해 인덱싱하며, 검색 엔진처럼 동작합니다. 예: MATCH(column) AGAINST('keyword').

  • Reverse Index: 문자열을 뒤집어 저장한 후 인덱싱해 접미사 검색을 지원합니다.

Q. 클러스터드 인덱스와 넌클러스터드 인덱스는 어떻게 다르며, 언제 사용하나요?

먼저 클러스터드 인덱스는 테이블 데이터를 특정 키 순서대로 물리적으로 정렬해 저장합니다.

그래서 테이블당 하나만 가능하고, 마치 책 내용 자체가 순서대로 정렬된 것과 같죠. 덕분에 범위로 검색하거나 정렬된 결과를 볼 때 아주 빠릅니다. 주로 기본 키에 사용되는데 다만, 데이터를 수정하거나 새로 넣을 때 재정렬 때문에 쓰기 작업이 좀 느려질 수 있다는 점은 생각해야 합니다.

반면에 넌클러스터드 인덱스는 데이터와는 별도로 '찾아보기'처럼 색인을 만들어두는 것입니다.

실제 데이터가 어디 저장되어 있는지 그 위치 주소를 가지고 있죠. 그래서 한 테이블에 여러 개 만들 수 있고, 특정 값을 찾거나 다양한 조건으로 검색할 때 유용해요. 데이터를 찾을 때 한 단계를 더 거칠 수는 있지만, 쓰기 부담은 클러스터드 인덱스보다 상대적으로 덜한 편입니다.

보통 기본키가 아닌 키에 인덱스를 설정하면 이 넌클러스터드 인덱스가 설정됩니다.

26MB
03-02_Index.wav