안녕하세요.
이번 게시글에선 자연키 기반 복합키와 인조키 기반 단일키를 PK로 사용하는 상황에 대해 비교해보겠습니다.
자연키 기반 복합키 VS 인조키 기반 단일키
1. 자연키 기반 복합키란?
- 자연키는 실제 데이터를 기반으로 한 고유 식별자이며, 복합키는 두 개 이상의 컬럼을 결합하여 유일성을 보장하는 키
2. 인조키 기반 단일키란?
- 실제 데이터와는 무관하게 시스템에서 생성된 임의의 고유 식별자. 주로 자동 증가 값이 쓰임
예상하는 상황) 복합키가 더 빠르다?
일반적으로 생각을 해보자면 복합키가 더 빠르다고 생각할 수 있습니다.
'복합 인덱스가 더 빠르다'라는 문구가 익숙하기 때문일 것 같은데요. 복합 PK키와 복합 인덱스키를 구분해야합니다.
일반적으로 조회 조건이 여러가지인 경우, 복수의 조회 조건에 인덱스를 태울 수 있기 때문입니다.
그러므로 '복합키(복합인덱스)는 빠르다' 라는 말이 맞는 상황입니다.
하지만 지금 보려는 상황인 복합 PK키에 대해 생각해보자면
복합키든 단일키든 PK로 조회 시 어차피 모든 조회 조건에 인덱스가 태워진 것으로 생각할 수 있습니다.
조회 조건을 키가 두개인 복합키인 PK로 조회되는 경우
첫 번째 조회 조건을 인덱스로 검색하여 검색대상의 후보를 절반씩 줄여가며 시간복잡도 O(logn)으로 조회할 수 있을 것입니다.
이후 조회 대상 중 나머지 조회 조건으로 검색을 해본다면 동일하게 후보를 절반씩 줄여가며 시간복잡도 O(logn)으로 조회할 것입니다.
이는 결국 단일키로 조회할 수 있는 시간복잡도 O(logn)과 동일한 것입니다.
그렇다면 예시 환경에서 검증을 해볼까요?
실제 성능 비교
mysql 데이터베이스 9.1.0 버전에서 검증을 진행했습니다.
아래와 같은 ddl문으로 각각의 테이블을 생성합니다.
복합키는 자연키 기반이므로 실제 비즈니스에서 쓰이는 데이터가 키가 되었습니다.
(그렇기 때문에 성능에 영향을 줄 거라고 생각했으나 영향 없었음 )
150만개 정도의 데이터 상황에선 조회 속도 거의 유사했습니다.
데이터의 건수가 많으면 달라지지 않을까 싶어서 1000만개의 데이터를 넣어서 비교해보았습니다.
1000만개 정도의 데이터 상황에서도 조회 속도가 차이가 없었습니다.
아래는 각각의 실행계획 결과입니다.
-- 자연키 기반 복합키
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.00"
},
"table": {
"table_name": "blog",
"access_type": "const",
"possible_keys": [
"PRIMARY"
],
"key": "PRIMARY",
"used_key_parts": [
"blog_url",
"rss_url"
],
"key_length": "2044",
"ref": [
"const",
"const"
],
"rows_examined_per_scan": 1,
"rows_produced_per_join": 1,
"filtered": "100.00",
"using_index": true,
"cost_info": {
"read_cost": "0.00",
"eval_cost": "0.10",
"prefix_cost": "0.00",
"data_read_per_join": "2K"
},
"used_columns": [
"blog_url",
"rss_url"
]
}
}
}
-- 인조키 기반 단일키
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "1.00"
},
"table": {
"table_name": "blog2",
"access_type": "const",
"possible_keys": [
"PRIMARY"
],
"key": "PRIMARY",
"used_key_parts": [
"id"
],
"key_length": "4",
"ref": [
"const"
],
"rows_examined_per_scan": 1,
"rows_produced_per_join": 1,
"filtered": "100.00",
"cost_info": {
"read_cost": "0.00",
"eval_cost": "0.10",
"prefix_cost": "0.00",
"data_read_per_join": "2K"
},
"used_columns": [
"id",
"blog_url",
"rss_url"
]
}
}
}
조회 속도는 동일한 데 비하여,
자연키 기반 복합키의 인덱스 길이가 훨씬 긴 것을 볼 수 있습니다.
결론) 자연키 기반 복합키(PK)는 장점이 없다
자연키 기반 복합키와 인조키 기반 단일키는 성능적으로 다를 것이 없었습니다.
그러나 자연기 기반 복합키의 단점은 명확합니다.
일단 자연키이므로 인덱스의 길이가 증가합니다.
보통 비즈니스 의미를 지닌 데이터가 자동증가값보다 더 크기 때문입니다.
또한 복합키이므로 전체 인덱스의 길이 또한 * N개 되어 증가됩니다.
따라서 DB 메모리 관리 측면에서 부담이 가중됩니다.
게다가, 개발 측면에서도 개발자가 특정 데이터를 조회할 때마다 데이터를 두 개 이상 보내야합니다.
단순 GET 요청에도 길이가 긴 복수개의 키를 URL에 담아야하는데
이는 개발 생산성 측면에서도 좋지 못합니다.
결론의 결론)
PK에는 자연키 기반 복합키를 사용하지 말자.
혹시라도 제가 놓친 부분 혹은 다른 의견 있으시다면 댓글로 남겨주세요!