데이터베이스 인덱스

정웅·2025년 11월 27일

데이터베이스

목록 보기
1/5
@Entity
@Table( name = "tracking_links", 
indexes = { 
@Index(name = "idx_tracking_links_slug", columnList = "slug", unique = true), 
@Index(name = "idx_tracking_links_campaign_id", columnList = "campaign_id"), 
@Index(name = "idx_tracking_links_creator_id", columnList = "creator_id") } )

1. 인덱스가 뭔데?

  • 인덱스 없음 = 책을 첫 페이지부터 끝까지 다 뒤지면서 단어 찾기 (전체 테이블 풀 스캔)
  • 인덱스 있음 = 책 맨 뒤에 ‘찾아보기’(index) 보고 바로 페이지로 점프

DB에서도 비슷하다.

SELECT * FROM tracking_links
WHERE slug = 'abc123';
  • slug 에 인덱스가 없으면 → tracking_links 테이블 전체를 한 줄 한 줄 다 읽어보면서 slug='abc123' 찾음.
  • slug 에 인덱스가 있으면 → 인덱스 구조(B-tree 등)에서 abc123 위치를 바로 찾아가서, 거기 연결된 row만 읽어옴.

즉, 자주 WHERE, JOIN, ORDER BY에 쓰는 컬럼에 인덱스를 걸어두면 조회 성능이 크게 좋아진다.
대신, INSERT/UPDATE/DELETE 할 때 인덱스도 같이 갱신해야 해서 쓰기 비용은 조금 늘어남.

2. @Index?

1)
slug 컬럼에
이름이 idx_tracking_links_slug 인 인덱스 생성
unique = true → 유니크 인덱스 (slug 값 중복 불가)

2)
campaign_id 컬럼에 인덱스 생성
→ WHERE campaign_id = ? 같은 조건 / JOIN 에 쓰일 때 빨라짐.

3)
creator_id 컬럼에 인덱스 생성
→ WHERE creator_id = ? 조건 / JOIN 때 빨라짐.

=> Hibernate가 ddl-auto=create/update 같은 설정이면, DB에 테이블 만들 때 이런 인덱스도 같이 생성해준다.

3. 왜 이 세 컬럼에 인덱스를 걸었을까?

1) slug (짧은 코드라는 말이다.)

@Column(nullable = false, unique = true, length = 50)
private String slug;
  • /t/{slug}로 들어올 때
  • DB에서
Select * From tracking_links where slug = ?;

이런 쿼리를 정말 자주 날리게 될 것이다.
그래서 slug는 lookup key 역할이고, 여기에 인덱스를 거는게 좋다.

2) campaign_id, creator_id

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "campaign_id", nullable = false)
private Campaign campaign;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "creator_id", nullable = false)
private Creator creator;

서비스 입장에서는 이런 쿼리를 많이 쓰게 될 것이다.

-- 캠페인별로 모든 트래킹 링크
SELECT * FROM tracking_links WHERE campaign_id = ?;

-- 크리에이터별로 모든 트래킹 링크
SELECT * FROM tracking_links WHERE creator_id = ?;

campaign_id, creator_id는 외래키 + 조회 조건으로 자주 쓰이는 컬럼이라 인덱스를 거는 게 거의 관례이다.

외래키라고 해서 자동으로 인덱스까지 같이 만들어주는 DB도 있긴하다, 하지만 무조건은 아니기에 JPA에서 명시적으로 인덱스를 걸어주는 패턴이 많이 쓰인다.

4. 요약

  1. 역할
  • 조회(Select) 속도를 올리기 위한 자료구조(보통 B-tree)
  • Where/Join/Order By/Group By에 자주 쓰는 컬럼에 건다
  1. 장단점
  • 장점 : Select 빨라짐
  • 단점 : Insert/Update/Delete 때 인덱스도 갱신해야 해서 비용 증가, 인덱스용 디스크 공간 차지
  1. 유니크 인덱스
  • unique = true = 해당 컬럼에서 중복을 허용하지 않는 인덱스
  • slug처럼 "고유 코드"에는 유니크 인덱스가 적합하다.

@Index = DB 인덱스를 JPA 코드 레벨에서 선언하는 것

지금 엔티티는:
slug로 빠르게 링크를 찾기 위해 인덱스 + 유니크 제약

campaign_id, creator_id로 빠르게 “캠페인별/크리에이터별 링크 목록”을 조회하기 위한 인덱스

profile
즐거운 개발 :) 신입 서버 개발자입니다

0개의 댓글