우리가 흔히 부르는 인덱스는 세컨더리 인덱스(B-Tree 알고리즘)이다.
그런데 중복이 허용되지 않은 컬럼에 추가된 인덱스를 유니크 인덱스라고 부른다. (NULL 값도 가능하다.)
둘은 구조상 아무런 차이점이 없다.
두 인덱스의 읽기와 쓰기는 성능에서 차이를 보인다.
유니크 인덱스는 세컨더리 인덱스보다 근소하게 빠르다.
이는 유니크 인덱스의 알고리즘이 특별하기 때문이 아니라 레코드 수가 적기 때문이다.
세컨더리 인덱스는 유니크 인덱스와 동일하게,
디스크 읽기를 통해 데이터를 가져온 뒤, CPU에서 컬럼값을 비교하는 과정에서 좀 더 진행할 뿐이다.
즉, 읽어야 할 레코드 수가 적어서 근소하게 빠를 뿐이다.
무작정 성능이 좋아질 것이라 기대하고, 유니크 인덱스를 적용하는 것은 의미없는 일이 될 수 있다.
유니크 인덱스에 데이터를 추가하거나 변경하는 경우, 세컨더리 인덱스의 경우보다 느리다.
데이터를 추가하기 전에, 기존에 있던 데이터와 중복된 값이 있는지 없는지를 체크해야 하기 때문이다.
디테일하게 보면, 유니크 인덱스 쓰기가 훨씬 더 느린 요인은 2가지이다.
1. MySQL에서 유니크 인덱스에서 중복된 값을 체크할 때, 읽기 잠금을 쓰고,
쓰기를 할 때, 쓰기 잠금을 사용하는데, 이 과정에서 데드락이 자주 발생한다.
2. InnoDB 스토리지 엔진에서 인덱스 키의 저장을 버퍼링하기 위해, 체인지 버퍼(Change Buffer)가 사용된다.
하지만, 유니크 인덱스에는 중복 체크가 필수이므로, 유니크 인덱싱 작업을 버퍼링하지 못한다.
인덱스 읽기에서 설명한 것처럼, 성능 향상을 위해 유니크 인덱스가 적용할 이유는 없다.
세컨더리 인덱스가 적용된 컬럼에 Unique Index가 적용될 이유도 없다.
(세컨더리 인덱스가 적용된 컬럼은 중복된 값이 올 수 있으므로)
Primary Key와 Unique Index를 동일하게 생성하는 것 또한 비효율적인 일이다.
(PK값 자체로 이미 Table에서 유일한 값이므로)