인덱스는 데이터베이스에서 데이터를 빠르게 검색하고, 조회하기 위한 자료구조이다. 사전 뒷편에 있는 찾아보기와 같은 역할을 한다고 생각하면 된다. 인덱스는 특정 칼럼 또는 칼럼의 조합에 대한 값과 해당 값이 존재하는 테이블 내의 물리적인 위치를 매핑한다. 이를 통해 데이터베이스는 효율적으로 데이터를 검색하고 필요한 정보를 빠르게 가져올 수 있다.
가장 일반적으로 사용되는 인덱스 유형으로, 검색 및 정렬 작업에 효과적
데이터를 B-Tree 구조로 저장하여 빠른 검색이 가능하다.
B-Tree의 각 노드는 배열로서 실제 메모리 상에 저장이 되어 있다. 같은 노드 공간의 데이터들끼리 굳이 자식 노드처럼 참조 포인터 값으로 접근할 필요가 없는 것이다. 즉 같은 노드 안에서 데이터를 탐색할 때, 포인터 접근이 아닌 실제 메모리 디스크에서 바로 다음 인덱스에 접근을 하게 된다.
위 사진에서 200이라는 값을 찾는다고 가정해보자. 순서는 다음과 같다.
1. 루트 노드에서 100, 155, 226을 탐색한다. 순차적으로 저장됐기에 빠르게 탐색할 수 있다.
2. 루트 노드에 200이 없기 때문에, 155와 226 사이의 포인터가 존재하는 지 확인 후 해당 포인터를 통해 자식 노드로 접근한다.
3. 자식 노드로 가 168, 200을 탐색 후 200을 찾아낸다. 이 과정 또한 순차적으로 저장됐기에 빠르다.
위에서 말했듯, 클러스터 인덱스와 보조 인덱스는 모두 B-Tree로 만들어진다.
B-Tree에서 데이터가 저장되는 공간을 노드라고 하고, MySQL에서는 이러한 노드들을 페이지라고 부른다.
MySQL에서는 페이지를 나누어 데이터를 저장하는데, 페이지는 MySQL 기준 최소 16KB의 크기를 가지며 페이지 데이터 공간이 추가적으로 필요할 경우 페이지 분할 작업을 통해 페이지를 생성하고 분할하는 작업을 거친다. 이 작업이 자주 일어나게 되면 데이터베이스 성능에 큰 영향을 미친다.
CREATE [UNIQUE] INDEX 인덱스 이름
ON 테이블 이름 (열 이름) [ASC | DESC]
DROP INDEX 인덱스_이름 ON 테이블_이름
SHOW INDEX FROM 테이블 이름
EXPLAIN
Query...
CREATE TABLE table1(
uid INT(11) NOT NULL auto_increment,
id VARCHAR(20) NOT NULL,
name VARCHAR(50) NOT NULL,
address VARCHAR(100) NOT NULL,
PRIMARY KEY('uid'),
key idx_name(name),
key idx_address(address)
)
CREATE TABLE table2(
uid INT(11) NOT NULL auto_increment,
id VARCHAR(20) NOT NULL,
name VARCHAR(50) NOT NULL,
address VARCHAR(100) NOT NULL,
PRIMARY KEY('uid'),
key idx_name(name, address)
)
Table 1은 name과 address에 대한 단일 인덱스, Table 2는 (name, address)에 대한 다중 컬럼 인덱스를 설정했다.
SELECT * FROM table1 WHERE name='홍길동' AND address='경기도';
Table1의 경우 단일 인덱스가 걸려있기 때문에 name과 address 중 어떤 컬럼이 더 빠르게 검색되는지 판단 후 빠른쪽을 먼저 검사라게 된다.
Table2의 경우 name과 address를 같이 저장하기 때문에 검색 시에도 '홍길동경기도'와 같이 검색을 시도하고, 바로 원하는 값을 찾을 수 있다.
SELECT * FROM table2 WHERE address='경기도';
반면 Query2의 경우, Table 1에서는 address 인덱스가 적용되지만, Table 2에서는 인덱싱이 적용되지 않는다. name이 사용되지 않았기 때문이다