본문 바로가기

데이터베이스/SQL & PL/SQL

[SQL] 색인기능, INDEX!


 여러분은 보통 책에서 원하는 정보를 찾을때 어떻게 찾으세요?
 단순히 책을 처음부터 한장한장 찾으시면서 찾으시진 않으시겠죠?

 다들 앞부분에 있는 목차를 찾거나 뒤의 색인 또는 INDEX를 찾아서 원하는 키워드를 찾아 해당 페이지를 펼칠 겁니다.
이렇게 데이터베이스에서도 해당 정보를 찾을때 책의 뒷편에서 볼수 있는 인덱스(INDEX)를 이용합니다.

 보통 데이터베이스는 엄청난 자료를 저장하고 있기때문에 하나의 자료를 찾기 위해서는 사람이 책에서 정보를 찾듯,
두가지 방법을 쓸 수 있는데요.

 데이터베이스에서 원하는 정보(데이터)를 담고 있는 테이블 전체를 메모리에 저장시켜서 찾는 방법, 
그러니까 저장되어 있는 데이터를 처음부터 이잡듯 뒤져서 정보를 찾는 겁니다. 이를 'FULL-TABLE SCAN' 방식이라고 데이터 베이스에서는 일컫습니다. -그저 '풀스캔'한다~ 고 표현하더군요.-

 그리고 다음으로는 테이블 전체를 메모리에 올리는 'FULL-TABLE SCAN' 방식과는 달리, 책에서 인덱스를 이용해서 원하는 정보를 찾는것처럼,
INDEX 정보를 이용해서 원하는 데이터를 담고 있는 데이터블록에 접근합니다. 그렇다 보니 모든 데이터를 불러오는 풀스캔 방식보다는,
INDEX를 이용한 방식이 디스크의 I/O를 줄임으로써 성능 향상을 꾀할 수 있습니다.

 그렇다고 해서 무조건 인덱스를 사용하는 것이 성능향상에 도움이 되는 것은 아니니 참고하시길 바랍니다.
 어떤 이유에서 그런지는 뒤에서 다루도록 하겠습니다.

 우선 인덱스를 만드는 방법입니다.
 인덱스는 UNIQUE나 PRIMARY KEY 등 어떤 제약조건으로 작용하는 것이 아니라 시퀀스 처럼 하나의 Object로 구성이 되기때문에,
CREATE 구문을 통해서 만들어 주도록 합니다.
CREATE UNIQUE INDEX 스키마.인덱스명 ON 스키마명.테이블명(컬럼1, 컬럼2, ...);

 위와 같이 스키마 명을 임의로 설정 후, 해당 테이블의 어떤 컬럼을 인덱스로 만들어 줄 것인지 지정해 줄 수 있습니다. 
그리고 UNIQUE 속성은 생략할 수도 있는데 UNIQUE를 적게되면 인덱스 생성시에 중복 값의 입력을 막아버립니다.

 한 테이블에 인덱스를 만들시에 컬럼을 한개 이상 만들 수 있는데, 이때를 '복합 인덱스'라 하고, 반대로 한개의 컬럼에 대해서는 '단일' 인덱스라고 합니다. 그리고 UNIQUE의 설정에 따라 'UNIQUE 인덱스' 또는 'NON-UNIQUE 인덱스'라고도 불리우는데, UNIQUE를 생략하게 되면 NON-UNIQUE로 설정됩니다.

 복합 인덱스에서 UNIQUE가 설정되어 있을때는 각각의 컬럼에 대해서 UNIQUE가 적용되는 것이 아니라, 그 조합에 대해서 UNIQUE 속성이 적용됩니다. 제약조건에 관한 글에서 UNIQUE 관련 부분을 보시면 이해 되실겁니다.

 그리고 테이블에서 UNIQUE 나 PRIMARY KEY 제약조건을 설정해주게 되면 자동으로 그 컬럼에 대해서 UNIQUE 인덱스가 만들어지는데요,
이렇게해서 만들어지는 인덱스는 '자동 인덱스'라 부르고, 반대로 우리가 직접 만들어 주는 인덱스에 대해서는 '수동 인덱스'라 부릅니다. 

 그렇다면, 데이터베이스는 어떻게 인덱스를 이용할까요?
 만일에 hr스키마에 대해서 employees 의 'last_name' 컬럼에 대해서 인덱스를 만들었다고 합시다. select문을 써서 데이터를 조회시에 where절에서 조건을 'last_name'을 쓰게 된다면 기 생성된 인덱스에서 해당 인덱스 정보를 찾은 그 정보와 함께 저장된 ROW ID를 통해 본래 테이블의 데이터를 조회합니다.

 조금 이해가 안되실 수도 있는데 다음의 인덱스를 통한 검색 방법을 살펴보시면 이해가 될 겁니다.
참고로 인덱스를 생성할때 인덱스의 컬럼(생성시 지정한)의 값들과 그 해당 값들의 ROW ID로 구성이 됩니다.
그리고 인덱스가 구성이 될때 컬럼은 정렬이 보시는 바와 같이 정렬이 됩니다.
다음에서 보실 수 있는 ROWID는 해당 데이터에 바로 Access 할 수 있는 주소 값입니다.

 


 인덱스를 이용하지 않을때는 모든 데이터의 로우들의 컬럼들을 조회할텐데,
인덱스를 이용할때는 해당 컬럼만을 조회해서 검색한후 ROW ID를 조회해 보다 빠른 결과를 얻을 수 있습니다.
ROW ID에 대해서는 다른글에서 살펴보기로 합시다.

 하지만 모든 상황에 대해서 인덱스가 효율적인것만은 아닌데요. 그러한 상황은 다음과 같습니다.
 1. 테이블의 데이터 즉, 로우가 적을때
   - 이때는 전체 검색이 더 빠른데, 굳이 인덱스를 만들어서 그것을 경유해서 조회할 필요는 없습니다.
 2. 테이블에서 조회할 양이 많을때
   - 만약 100억건의 데이터에서 내가 90억건의 데이터를 조회할 경우에는 위와 똑같은 이유로, 인덱스를 사용하는 것이 더 느립니다.
   - 반면에 조회할 양이 적을 경우에는 인덱스가 효율적입니다. 

 그렇다면 어떤 컬럼을 인덱스로 지정하는 것이 좋을까요? 
 1. 자주 사용하는 컬럼 
 2. 조인에 사용되는 컬럼
 3. 참조 제약조건이 있는 컬럼
 
등이 있겠고, 복합 인덱스를 구성시에는 더 자주 사용되는 컬럼을 인덱스의 앞쪽으로 구성합니다.

어떠세요? 인덱스에 대해서 이해에 도움이 되었는지 모르겠네요.

다음글에서는 인덱스의 종류중에서 가장 많이 쓰이는 B-tree에 대해서 알아보도록 할게요.
다음링크를 따라가셔도 됩니다.
B-tree에 대해서 알아보기


도움 되셨다면 밑의 추천(손가락 표시)과 댓글 부탁드립니다.