@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") } )
DB에서도 비슷하다.
SELECT * FROM tracking_links
WHERE slug = 'abc123';
즉, 자주 WHERE, JOIN, ORDER BY에 쓰는 컬럼에 인덱스를 걸어두면 조회 성능이 크게 좋아진다.
대신, INSERT/UPDATE/DELETE 할 때 인덱스도 같이 갱신해야 해서 쓰기 비용은 조금 늘어남.
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에 테이블 만들 때 이런 인덱스도 같이 생성해준다.
1) slug (짧은 코드라는 말이다.)
@Column(nullable = false, unique = true, length = 50)
private String slug;
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에서 명시적으로 인덱스를 걸어주는 패턴이 많이 쓰인다.
@Index = DB 인덱스를 JPA 코드 레벨에서 선언하는 것
지금 엔티티는:
slug로 빠르게 링크를 찾기 위해 인덱스 + 유니크 제약
campaign_id, creator_id로 빠르게 “캠페인별/크리에이터별 링크 목록”을 조회하기 위한 인덱스