유니크 인덱스는 인덱스에 제약조건을 걸어둔거라고 생각할 수 있다. 그런데 사실 MySQL에서는 인덱스 없이 유니크 제약만 설정할 순 없다.
유니크 인덱스에는 NULL값도 저장 가능함. NULL은 특정한 값으로 취급되는게 아니므로, 유니크임에도 2개 이상 저장될 수 있다.
MySQL에서 PK는 기본적으로 NOT NULL + 유니크 속성이 자동으로 부여된다.
유니크 인덱스와 유니크하지 않은 일반 세컨더리인덱스는 구조상에서는 사실 아무런 차이가 없다. 읽기와 쓰기에서의 차이를 성능 관점에서 한번 보자.
유니크 인덱스는 빠를까? 어떤 책에서는 유니크 인덱스는 1건만 읽으면 되지만, 그게 아닌 세컨더리 인덱스는 레코드를 몇건 더 읽어야 하므로 상대적으로 느리다록 한다.
그러나 유니크하지 않은 세컨더리 인덱스에서 일어나는 일은 디스크 읽기가 아니라 (이건 여전히 한번만 일어난다) CPU가 칼럼값을 비교하는 작업이라 사실 성능상에는 큰 차이가 없다. 즉, 그냥 인덱스를 몇건 더 읽었기 때문에 비교하는 작업이 좀 추가되었을 뿐이지, 세컨더리 인덱스도 인덱스를 한건만 읽는다면 성능상에는 차이가 없다. (옵티마이저는 실행계획은 다르게 표시하긴 한다.)
유니크인덱스는 값을 쓸때 중복된 값이 있는지 없는지 체크하는 과정이 하나 더 필요하다. 때문에 쓰기에서는 일반 세컨더리 인덱스보다 좀 더 느리다. 그리고 MySQL에서는 유니크 인덱스에서 중복된 값을 체크할때는 읽기 잠금을 사용하고, 쓰기할때는 쓰기 잠금을 사용하는데 이 과정에서 데드락이 아주 빈번히 발생한다. 또한 InnoDB는 인덱스 키의 저장을 버퍼링 하기 위해 체인지 버퍼를 사용하는데, 유니크 인덱스는 중복체크때문에 키를 버퍼링 하지 못한다. 그래서 유니크 인덱스는 일반 세컨더리 인덱스보다 쓰기 작업은 더 느리다.
꼭 필요한 경우에 사용하는건 당연하지만 성능의 이점을 볼 생각으로 사용하는건 좋지 않다. 또한 MySQL의 유니크 인덱스는 여전히 일반 세컨더리 인덱스와 동일한 기능을 하므로 중복해서 만들어 둘 필요도 없다. 심지어 어떤 경우에는 똑같은 컬럼에 PK와 유니크 인덱스를 생성하기도 한다. 이 역시 매우 불필요하다. 오직 유일성이 보장되어야 하는 경우에만 유니크 인덱스를 사용하자.