CREATE table TMP_SAMPLE(
phone_num varchar(255) not null,
opening_date timestamp,
insert_date timestamp DEFAULT CURRENT_TIMESTAMP,
now_date timestamp DEFAULT CURRENT_TIMESTAMP,
primary key(phone_num, insert_date, opening_date)
) charset = utf8;
복합키란 위 SQL문의 primary key처럼 여러개의 컬럼으로 하나의 Primay Key를 만드는 방법이다.
이번에 회사에서 복합키를 통해서 SQL문을 작성하였었다.
중요한 것은 왜 복합키를 통해서 SQL문을 작성하였고, 이 때 장점과 단점은 무엇인지를 생각해내는 것이다.
먼저 복합키의 단점에 대해서 먼저 알아보자.
FK를 다른 테이블과 맺을 때 사이드 이펙트가 크다.
→ 위 TMP_SAMPLE과 외래 관계를 맺고 싶을 때 대다수 숫자인 ID에 비해서 복합키에 해당 하는 필드들 모두 해당 테이블에 속해야하는 문제가 있다.
인덱스에 좋은 영향을 주지 못한다.
→ PK 컬럼은 인덱스가 자동으로 걸리는데, 복합키를 사용하면 복합키 중 하나의 컬럼만을 조회에 사용한다면 이 때 인덱스가 적용되지 않는다.
위 쿼리에서 예를 들어서 phone_num, insert_date, opening_date 중 insert_date만을 복합키로 사용할 경우에는 인덱스가 적용되지 않을 수 있다.
정확히는 조건절에 복합키의 순서대로 조합하지 않는다면 PK 인덱스는 타지 않거나 일부만 탄다.
아래는 조회시에 인덱스가 걸리는 조합들이다.
phone_num, insert_date, opening_date
phone_num, insert_date
phone_num
일반적으로 복합키는 카디널리티가 높은 곳에서 낮은 순으로 구성하되(= 데이터의 중복이 높은), 조회 / 입력 방법에 따라서 적절히 순서를 바꿔서 구성하거나 새로 인덱스를 추가하면 된다.
→ 카디널리티가 높은 순에서 낮은 순으로 해야 하는 이유는 복합키는 적힌 순서에 따라서 인덱스가 결정되기 때문에, 많이 중복 되면 인덱스의 효과가 덜하기 때문이다.
카디널리티 → 특정 데이터 집합의 유니크한 값의 개수
제약 조건 변경시 PK 전체 수정이 필요하다.
→ 복합키에 필요한 필드들의 제약조건이 변경된다면 PK 전체 수정이 발생할 수도 있다. 또한 대란 테이블과 FK를 맺고 있다면 또한 해당 테이블의 내용도 모두 바꿔줘야 하는 문제가 생긴다.
이러한 단점들에도 불구하고 왜 복합키를 사용할까?
→ 만약 테이블에 특정 데이터를 식별하는게 큰 필요가 없고, 단순히 수치와 같은 조회를 위한 통계성 데이터들에 가깝다면 복합키를 사용해봐도 좋다. ID라는 식별자를 별도로 둘 필요도 없고, 복합키를 통한 조회로 PK 인덱스 또한 잘 활용할 수 있다.
JPA에서는 알파벳 순서대로 복합키 순서를 적절히 구성한다.
이러한 방법은 PK를 효율적으로 사용하기 부적합한 방식이다.
위에서 카디널리티를 고려하여서 복합키 순서를 구성해야한다고 이야기했었다. 그러나 알파벳 순서로 복합키 순서를 정해버리면, 이를 고려할 수 없게 되기 때문이다.
이러한 문제를 해결하기 위해 DB에서 직접 복합키를 구성하는 방식을 취할 수 있다.