앞의 내용에서 사용한 힙 테이블을 기준으로 클러스터드 인덱스만을 가지는 테이블을 만들어 보자. 방법은 넌 클러스터드의 경우와 유사하며, 다만 리프 레벨 페이지가 직접 데이터 페이지가 된다는 점만이 다르다.


그림을 보면 실제 데이터 페이지 자체를 정렬해서 이것이 리프 레벨노드로 사용되고, 그 위에 넌 리프 레벨 노드와 루트 노드가 생성되었음을 알 수 있다. 데이터 페이지가 많지 않아 중간 레벨 노드들은 없었다. 기존 RID 대신에 최종 레벨 노드들은 인덱스 페이지의 첫 번재 로우값을 가지게 된다. 포인터 점프 대신에 데이터 페이지의 첫 첫번째 컬럼 값을 가지고 해당 데이터 페이지로 이동하여 데이터 페이지의 첫 번째 값부터 순차적으로 읽어 들이게 된다.
 
클러스커드 인덱스에서 값을 조회해보자. 검색할 데이터는 번호가 4번인 데이터이다. 역시 데이터 검색은 루트 노드부터 시작하게 된다. 루트노드에서 값이 4번인 것은 데이터 페이지 1에 있다는 것을 알 수 있다. 중간 레벨 노드들이 많았다면 아마도 몇 가지 레벨에 거쳐서 이러한 탐색 단계들을 진행해야만 할 것이다.


참고서적:Deep Inside T-SQL

크리에이티브 커먼즈 라이센스
Creative Commons License 이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
트랙백 주소: http://ggoma.isblog.net/trackback_post_447.aspx

댓글을 달아 주세요

아래<그림>은 클러스터드 인덱스가 없는 넌 클러스터드를 나타낸다. 첫 번째 레벨과 두 번째 레벨까지의 노드들은 인덱스 페이지들이며, 가장 하위의 것은 트리의 리프 레벨 노드들이 아니라 무작위로 저장되어 있는 데이터 페이지들이다. 그림에서는 intermediate레벨 노드들은 존재하지 않고 루트 노드와 리프노드로 직접 구성되어 있다. 리프 노드들은 데이터 페이지로의 포인터(이를 Row ID 혹은 RID(Relative Identifier)라고 부르기도 한다.)를 링크하고 있다.


이렇게 실제 데이터를 가져오기 위해서 리프 노드에서 데이터 페이지로 이동하는 것을 포인터 점프(Pointer Jump)라고 부른다. 클러스터드 인덱스에서는 리프 레벨이 데이터 페이지이므로 이러한 포인터 점프가 필요 없다. 포인터 점프는 쿼리의 퍼포먼스에 영향을 미칠 수도 있다.
 

좀더 실제적인 예를 가지고 살펴보자 우선 클러스터드든 넌 클러스터드든 아무런 인덱스도 설정되지 않은<그림1>와 같은 테이블이 있다. 이렇게 아무런 인덱스도 설정되지 않은 테이블을 힙 테이블(Heap Table)라고 한다. 데이터는 정렬되어 있지 않고 무작위로 들어 있다. 컬럼은 번호, 이름, 주소, 나이 순으로 되어 있고, 모두 11개의 로우들로 구성되어 있는 간단한 주소 테이블이다.
 

                                                            <그림1>

이 테이블의 데이터 페이지 구성은 <그림2>과 같으며, 무작위 순으로 되어 있다. (예제를 간단히 표현하기 위해서 하나의 데이터 페이지에는 모두 4개의 로우들만 들어 갈 수 있다고 가정 하였다)

                                                             <그림2>
 
모두 3개의 데이터 페이지로 구성되어 있으며 페이지 1과2는 모두 채워져 있고 페이지 3은 여분으로 로우 하나가 더 추가 될 수 있다.(실제 상황이라면 이렇게 로우 개수를 기준으로 데이터 페이지가 채워지는 것은 아니다. 당연히 로우가 가진 실제 데이터에 맞추어서 저장 되어진다.)
 
데이터 페이지에 저장된 것은 컬럼의 정열 순서와는 아무런 상관도 없다. 순전히 데이터가 추가된 순서라고 할 수 있다. 예를 들어 번호가 1인 김수영 로우가 가장 먼저 Insert 되고, 다음에 5번인 김시원 데이터가 저장되었다.
 
이를 번호 순으로 정렬하면 <그림3>과 같은 리스트가 만들어진다. 옆에 있는 Row ID는 앞에 강좌에서 설명한 것처럼 데이터 파일, 데이터페이지 번호, 로우 번호로 구성되는 것으로써 그림에서 번호 2의 경우 ‘1-1-1’ 1번 데이터 파일에 1번 페이지의 1번 로우라는 데이터 페이지 포인터 값을 가상으로 표현한 것이다. 일단 정렬된 리스트가 있으면 이를 인덱스 페이지로 구성하는 것은 매우 간단하다.

 

넌 클러스터드 인덱스를 만드는 것은 어려운 일이 아니다. 인덱스 컬럼으로 선택된 컬럼들을 기준으로 데이터 페이지를 정렬해서 이를 B-Tree로 구성하고, 리프 레벨에서는 실제 데이터페이지로 링킹 될 수 있도록 RID를 매팅한다.


클러스터드 인덱스가 없는 넌 클러스터드 인덱스 상황에서 원하는 값을 찾을 때 어떻게 수행되는지를 알아보자. 인덱스의 구축은 최하위 레벨인 리프 레벨에서부터 루트 노드로 상향식으로 이루어졌지만, 탐색은 정반대로 루트 노드에서 리프 레벨 노드로 이루어진다. 우선 번호 15를 가지고 루트 노드의 로우들과 비교한다. 

여기서 로우 아이디를 기준으로 포인터 점프(Pointer Jump)를 한다. 포인터 점프는 데이터 페이지로 링크하는 것이다.




크리에이티브 커먼즈 라이센스
Creative Commons License 이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
트랙백 주소: http://ggoma.isblog.net/trackback_post_446.aspx

댓글을 달아 주세요


인덱스는 클러스터드 인덱스와 넌 클러스터드 인덱스 두가지로 나눌 수 있다. 두 인덱스 간의 차이는 클러스터드 인덱스는 테이블 당 오직 하나만 생성할 수 있고, 넌 클러스터드 인덱스는 여러 개를 생성할 수 있다는 것이다.
 
인덱스는 모든 데이터를 B-Tree 형식으로 정렬해 놓게 된다. 클러스터드 인덱스는 키로 설정된 컬럼을 B-Tree 형식으로 정렬해 놓는데, 리프 레벨에서 아예 데이터 페이지 자체를 정렬해 놓는다. 이에 반해서 넌 클러스터드 인덱스는 별도의 인덱스 페이지를 생성하여 이를 관리한다. 그러므로 데이터 페이지 자체를 정렬해놓는 클러스터드 인덱스는 더 이상 추가가 불가능한 것이다.
 
인덱스 페이지의 구조는 이렇게 해당 테이블에 클러스터드 인덱스가 있느냐 아니면 넌 클러스터드 인덱스이냐에 따라 다른 구조를 띄게 된다. 좀더 정확히는 클러스터드 인덱스가 없는 넌 클러스터드 인덱스냐, 클러스터드가 있는 넌 클러스터드 인덱스이냐에 상관하는 형태를 가진다는 것이다. 


참고서적:Deep Inside T-SQL


크리에이티브 커먼즈 라이센스
Creative Commons License 이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
트랙백 주소: http://ggoma.isblog.net/trackback_post_439.aspx

댓글을 달아 주세요