Skip to content
난이도 문제은행 6

유니크 인덱스 ​

유니크 인덱스(unique index)는 같은 값이 두 번 들어가지 못하게 막는 중복 금지 제약이면서, PK(Primary Key, 기본 키)가 아닌 칼럼으로 만드는 보조 인덱스인 세컨더리 인덱스(secondary index)이기도 하다. 일반 세컨더리 인덱스와의 차이는 키 하나로 멈추는 탐색과 잠금 범위 축소다.

일반 세컨더리와의 비교 ​

유니크일반 세컨더리
중복 허용✕ (NULL은 여러 개 가능)◯
동등 탐색한 건 찾으면 중단뒤에 같은 키가 있는지 더 봄
잠금(FOR UPDATE)레코드 락(record lock)으로 축소 가능넥스트키 락(next-key lock) 범위 잠금
용도업무 키(natural key) 보장조회 가속

NULL 처리가 함정이다. 유니크 칼럼에 NULL이 여러 개 들어가도 위반이 아니다(MySQL 기준). "NULL 없음"까지 원하면 NOT NULL을 함께 건다.

잠금 차이 — 왜 면접 단골인가 ​

FOR UPDATE는 읽은 행을 다른 트랜잭션(transaction)이 고치지 못하게 잠그면서 읽는 구문이다. 기본 격리 수준(isolation level)인 REPEATABLE READ에서 유니크 칼럼 uk에 WHERE uk = ? FOR UPDATE를 실행하고 일치하는 행이 있으면, 키 하나로 행이 확정된다. 그래서 InnoDB가 레코드 사이 빈 구간을 잠그는 갭 락(gap lock)까지 걸 필요가 없어, 그 행 하나만 잠그는 레코드 락으로 축소된다. 일치하는 행이 없으면 그 값이 들어갈 자리를 막아야 하므로 갭 락이 여전히 걸린다. 반면 일반 세컨더리 인덱스의 동등 조건은 뒤에 같은 키가 있을지 몰라 넥스트키 락으로 잠근다. 쿠폰 발급·좌석 선점처럼 여러 요청이 같은 유니크 키를 동시에 노리는 경합 상황에서 체감되는 차이다.

사용 시 주의사항 ​

  1. 복합 유니크 순서: (a, b) 복합 유니크는 a와 b의 조합이 같을 때만 중복으로 본다. 맨 왼쪽 칼럼부터 조건이 있어야 인덱스 탐색에 쓸 수 있다는 좌측 접두어 규칙(leftmost prefix rule)도 그대로 적용된다.
  2. 길이 제한: 인덱스 키 길이 한도는 행을 어떤 형식으로 저장할지 정하는 행 포맷(row format)에 따라 다르다. 기본 16KB 페이지(page)에서 DYNAMIC·COMPRESSED 행 포맷은 최대 3072바이트, REDUNDANT·COMPACT는 767바이트다. 페이지 크기가 작으면 한도도 비례해 줄어든다. 긴 문자열은 앞부분만 인덱싱하는 접두어 인덱스(prefix index) 또는 문자열의 해시값을 담는 별도 칼럼을 검토한다.
  3. INSERT ... ON DUPLICATE: INSERT ... ON DUPLICATE KEY UPDATE는 유니크 충돌을 감지하면 삽입 대신 기존 행을 업데이트한다. 한 문장이 중간에 끊기지 않고 처리되는 원자적 업서트(upsert, 없으면 삽입하고 있으면 갱신)다. 결과로 돌아오는 영향받은 행 수(affected rows)는 행마다 새로 삽입하면 1, 기존 행을 갱신하면 2, 기존 행을 지금과 같은 값으로 두면 0이다(클라이언트가 CLIENT_FOUND_ROWS로 접속하면 0 대신 1). 그래서 이 값으로 삽입과 갱신을 구분할 수 있다. 유니크 인덱스가 둘 이상이면 조심한다. a와 b가 모두 유니크인 테이블에 (a, b) = (1, 2)인 행을 넣으면 이 문장은 UPDATE ... WHERE a=1 OR b=2 LIMIT 1처럼 동작해, 두 기존 행과 겹쳐도 한 행만 갱신된다. 매뉴얼도 유니크 인덱스가 여러 개인 테이블에서는 이 문법을 피하라고 권장한다. INSERT IGNORE·REPLACE와의 차이는 INSERT·UPDATE·DELETE 고급에서 본다.
  4. 대소문자: 문자열을 비교·정렬하는 규칙인 콜레이션(collation)에 따라 ABC와 abc가 같은 값 취급될 수 있다. 대소문자·악센트를 구분하는 utf8mb4_0900_as_cs 같은 규칙을 확인한다. 콜레이션이 비교에 미치는 영향은 문자열 타입과 문자 집합에서 본다.

면접 포인트 ​

  • "유니크와 PK의 차이?" → NULL 허용 여부 + 테이블당 1개 + 클러스터링 여부.
  • "유니크를 걸었는데 조회가 느려요" → 유니크는 중복을 막는 제약이지, 탐색은 일반 B-Tree와 같다. 잠금 축소는 FOR UPDATE 동등 조건에서.
  • "NULL이 여러 개 들어가요?" → 들어간다. 의도라면 NOT NULL 추가.

관련 문서