인덱스에서 클러스터링은 값이 비슷한 것들을 묶어서 저장하는 형태로 구현되는데, 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에 착안한 것이다.
MySQL에서 클러스터링 인덱스는 InnoDB와 TokuDB 스토리지 엔진에서만 지원하며, 나머지 스토리지 엔진에서는 지원되지 않는다.
클러스터링 인덱스는 테이블의 프라이머리 키에 대해서만 적용되는 내용이다. 즉 프라이머리 키값이 비슷한 레코드끼리 묶어서 저장하는 것을 클러스터링 인덱스라고 표현한다. 여기에서 중요한 것은 프라이머리 키값에 의해 레코드의 저장 위치가 결정된다는 것이다. 또한 프라이머리 키값이 변경된다면 그 레코드의 물리적은 저장 위치가 바뀌어야 한다는 것을 의미한다.
프라이머리 키값으로 클러스터링된 테이블은 프라이머리 키값 자체의 대한 의존도가 상당히 크기 떄문에 신중히 프라이머리 키를 결정해야 한다.
일반적으로 InnoDB와 같이 항상 클러스터링 인덱스로 저장되는 테이블은 프라이머리 키 가반의 검색이 매우 빠르며, 대신 레코드의 저장이나 프라이머리 키의 변경이 상대적으로 느릴 수 밖에 없다.

위 그림의 클러스터링 인덱스 구조를 보면 클러스터링 테이블의 구조 자체는 일반적인 B-Tree와 많이 비슷하게 닮아 있다. 하지만 B-Tree의 리프 노드와는 달리 클러스터링 인덱스의 리프 노드에는 레코드의 모든 컬럼이 같이 저장돼 있음을 알수 있다. 즉 클러스터링 테이블은 그 자체가 하나의 거대한 인덱스 구조로 관리되는 것이다.
그러면 프라미어리 키가 없는 InnoDB 테이블은 어떻게 클러스터 테이블로 구성될까? 프라이머리 키가 없는 경우에는 InnoDB 스토리지 엔진이 다음의 우선순위대로 프라이머리 키를 대체할 컬럼을 선택한다.
InnoDB 스토리지 엔진이 적절한 클러스터 키 후보를 찾지 못해서 내부적으로 자동 증가 컬럼을 추가한 경우, 자동 추가된 컬럼은 사용자에게 노출되지 않으며, 쿼리 문장에 명시적으로 사용할 수 없다.
MyISAM이나 MEMORY 테이블과 같은 클러스터링되지 않은 테이블은 INSERT될 때 한번 저장된 공간에서 절대 이동하지 안흔다. 데이터 레코드가 저장된 주소는 내부적인 레코드 아이디 역할을 한다. 그리고 프라이머리 키나 보조 인덱스의 각 키는 그 주소를 이용해 실제 데이터 레코드를 찾아온다. 그래서 MyISAM , Memory 테이블에서는 프라이머리 키와 보조 인덱스는 아무런 차이가 없다. 그렇다면 InnoDB 테이블에서 보조 인덱스가 실제 레코드가 저장된 주소를 가지고 있다면 어떻게 될까? 클러스터 키값이 변경될 때마다 데이터 레코드의 주소가 변경되고 그때마다 해당 테이블의 모든 인덱스에 저장된 주소 값을 변경해야 할 것이다. 이런 번거러움을 방지하고자 InnoDB 테이블의 모든 보조 인덱스는 해당 레코드가 저장된 주소가 아니라 프라이머리 키값을 저장하도록 구현되어 있다.