post_url
에 대한 key가 두개나 뜨는 것을 볼 수 있었다.
@Entity
@Table(
indexes = @Index(name = "idx_post_url", columnList = "postUrl")
)
public class Post extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;
...
@Column(unique = true, nullable = false)
private String postUrl;
세컨더리 인덱스로 지정하기 위해 @Index
를 사용한 것과 유니크성을 확보하기 위해 @Column
에 unique=true 설정을 준 것이 내부동작 이해를 제대로하지 못하여 키가 두개가 생성된 문제이다.
확인 해본 결과 @Index는 유니크는 보장하지 않는 Btree 인덱스를 생성하며,
unique=true 설정은 유니크를 보장하는 Btree 인덱스를 생성한다.
unique = true만 사용하도록 코드 수정
@Entity
public class Post extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "post_id")
private Long id;
...
@Column(unique = true, nullable = false)
private String postUrl;
unique = true
vs @Index
vs @UniqueConstraint(추가 조사)
unique = true
와 @Index
의 차이점@Index
는 B-Tree 인덱스를 생성하여 검색 성능을 향상시키지만, 중복을 허용한다.unique = true
는 B-Tree 인덱스를 생성하면서 동시에 유니크(Unique) 제약 조건을 부여하여 중복을 방지한다.unique = true
를 사용한다.@Index
를 사용한다.@UniqueConstraint
를 사용한다.@UniqueConstraint
란?unique = true
와 동일하게 유니크 제약 조건을 적용하지만, 두 개 이상의 컬럼을 조합하여 유니크 제약을 걸 수 있는 점이 다르다.📌 예제: username
과 email
을 조합하여 유니크 조건 설정
@Entity
@Table(
uniqueConstraints = { @UniqueConstraint(name = "UK_username_email", columnNames = {"username", "email"}) }
)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String username;
@Column(nullable = false, length = 100)
private String email;
}
username + email
의 조합이 중복되지 않도록 보장된다.unique = true
를, 여러 컬럼을 조합하려면 @UniqueConstraint
를 사용하면 된다.구분 | @Column(unique = true) | @Index | @UniqueConstraint |
---|---|---|---|
중복 방지 여부 | ✅ O (중복 불가) | ❌ X (중복 허용) | ✅ O (중복 불가) |
검색 성능 향상 여부 | ✅ O (B-Tree 인덱스 자동 생성) | ✅ O (B-Tree 인덱스 생성) | ✅ O (B-Tree 인덱스 생성) |
단일 컬럼 적용 가능 여부 | ✅ O | ✅ O | ✅ O |
두 개 이상의 컬럼 조합 가능 여부 | ❌ X | ✅ O (단순 인덱스) | ✅ O (복합 유니크 키) |
unique = true
사용 @Index
사용 @UniqueConstraint
사용 **즉, 중복을 방지하면서도 검색 성능을 향상시키고 싶다면 unique = true
를 선택하자.