C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
분야별 포럼
C++빌더
델파이
파이어몽키
C/C++
프리파스칼
파이어버드
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

자유게시판
세상 살아가는 이야기들을 나누는 사랑방입니다.
[15167] MS SQL 서버의 Clustered (클러스터) 인덱스에 대한 그릇된 이해.
주정섭 [jjsverylong] 6317 읽음    2008-10-06 15:47
간혹 개발자들과 이야기하다보면, 대체 어디서 주워들었는지 모르지만, 매우 황당한 사실을 미신처럼 믿고 그 방식대로 코딩 하거나, 전혀 근거없는 상식(?)을 주장하는 개발자들을 매우 자주 보곤한다. 해외에서는 이런 박수무당식의 허무 맹랑한 코딩 방식을 비꼬아서 부두 프로그래밍이라고 한다. 부두 프로그래밍이란, 자신만의 근거없는 편견과 오만으로, 전혀 근거없는 개발 사상으로 무장하고서 코딩하는 것을 말한다.

왜 이런 부두 프로그래밍이 난무하는지 아직도 아리송하지만, 대충 나의 경험에 의하면 많은 개발자들이 어떤 사실을 받아들일 때, 그 사실의 논리타당성을 검증하지 않고, 막무가내 혹은 지 편한대로 받아들인다는 것이다. 특히 비교적 많이 알려진 대가나 경험자들이 어떤 거짓사실을 유포하면, 그것의 옳고 그름을 따져보기보다는 그냥 마구 믿어버린다는 것이다. 대부분의 사람들은 책을 읽거나 해서 그 사실을 확인해보는 적극성을 가지기 보다는, 유명한 사람이 말하면 그냥 믿고 사용하는 것이 더 편하다고 생각하는 경향이 있는 것 같다.

그래서, 우리는 이명박씨의 말도 안되는 거대한 경제 공약을 너무나 쉽게 믿고, 그를 뽑아주는 실수를 저질렀는지도 모르겠다. 내 경험에 의하면, 쉽게 믿는 것 만큼 바보스런 짓이 없다는 것이다. 특히 이 개발업계에서는 모든 코딩적 개념은 반드시 확인하고 사용해봐야 한다.

과거 내가 경험했던 그런 무책임하고도 거짓 투성이인 개발 관련 속설들 중에서 아직도 빈번히 접하는 것의 예를 들면,

"RDB에서 Trigger는 결코 사용해서는 안되는 위험 천만한 도구다"
"델파이에서 DataAware Component들은 쓸데없이 Lock를 가중시키므로 결코 사용해서는 안된다",
"MS SQL 서버에서 Primay Key Index는 클러스터(clustered) 인덱스로 지정하는 것이 가장 효율적이다."

이런 말도 안되는 속설 중에서 마지막 항인, 과연 MS SQL 서버에서 PK는 클러스터 인덱스로 지정해야 하는 것이 옳은가를 따져 보자. 이글을 쓰기 전에 클러스터 인덱스를 제대로 아는 사람들이 주위에 있는지 물어봤지만, 상당수가 클러스터 인덱스의 기본 개념조차 모르고 있는 경우가 허다했다.

뭔가를 따져보려면, 그 근본 개념을 잘 알아야만 한다. 점을 믿는 것이 점에 대한 전혀 근거 없는 믿음에서 시작하듯이, 점쟁이들이 실제로 어떻게 점을 치는지를 따져보면 점이 얼마나 허무맹랑한 것인지 알 수 있다.

MS SQL 서버에서 어떤 인덱스를 Clustered로 지정하면, 그 테이블 내의 레코드들은 그 클러스터 인덱스의 키값대로 물리적으로 정렬된다고 한다. 이말인즉, 다음과 같은 공식이 성립한다는 것이다.

클러스터 인덱스 필드값들의 순서 == 레코드의 물리적 배열 순서

즉 인덱스 키값 순서대로 레코드가 자동으로 소트되어 저장되도록 보장한다는 것이 클러스터 인덱스의 기본 개념이다. 따라서 당연히 클러스터 인덱스는 테이블 당 하나만 존재한다. 하나의 테이블을 두가지 이상의 방식으로 동시에 물리적으로 정렬한다는 것은 불가능하기 때문이다.

여기서 클러스터 인덱스로 하면 합당한 필드의 성질이 자동으로 결정된다. 레코드 추가 순서대로 필드값이 계속 증가 혹은 감소하는 필드에 대해서, 클러스터 인덱스로 지정하는 것이 바람직하다는 것이다. 이러한 대표적인 필드의 예를 들면 자동증가(Auto increment) 필드이다. 이 경우, 레코드가 추가될 때 마다 물리적으로 재배치하는 작업이 아주 적게 발생하기 때문이다.

클러스터 인덱스인 경우, 기존의 인덱스 키값들보다 너무 크거나 작은 값이 제멋대로 들어올 경우, 기존 레코드의 물리적 순서를 완전히 재배치해야 하는 문제가 발생한다. 이 과정에서 Page Splitting라고 하는 매우 속도를 깨어먹는 작업이 수반된다.

클러스터 인덱스는 레코드 순서 자체가 인덱스이므로, 인덱스를 저장하기 위한 별도의 페이지를 할당할 필요가 없다. 이말인즉, 클러스터 인덱스를 사용하는 쿼리를 실행할 경우, 인덱스가 저장된 페이지에서 쿼리 조건에 해당하는 레코드 위치 자료를 얻어내는 작업이 생략된다는 것이다. 그래서 일반 인덱스에 비해서 검색 속도가 빠른 것이다.

그렇다면 클러스터 인덱스의 두번째 특성이 여기서 등장한다. csfield을 클러스터드 인덱스 필드라고 가정할 경우, where조건문에 csfield가 등장한다면, equal 조건 검색보다는 range 검색에 더 효과를 발휘한다는 것이다.

// 아래처럼 어떤값과 동등한가를 찾는 쿼리보다는
쿼리1) select * from table1 where csfield = 10

// 아래처럼 특정 범위 검색이 잦은 필드가 클러스터 인덱스에 합당하다.
쿼리2) select * from table1 where csfield >= 10 and  csfield <= 20
쿼리3) select * from table1 where csfield between 10 and 20

클러스터 인덱스를 설정해야할 대표적인 필드의 예로, 매출일자, 매입일자 등을 들수 있다. 매출일자와 매입일자는 그 특성상 레코드가 추가될 때 거의 증가하는 방향이다. 오늘이 1월 1이면 거의 대부분이 1월1일자의 매출일자로 추가되지 과거나 미래 날자로 매입 혹은 매출일자를 발생 시킬 경우는 거의 없다는 것이다. 또한 매출과 매입일자는 매우 빈번한 범위 검색의 대상이 된다. 매출과 매입일자는 한번 기록하면, 수정할 일이 거의 없는 필드이기도 하다. 즉, 레코드 재배치가 일어날 가능성이 가장 적은 필드에 해당한다는 것이다.

결론적으로, PK는 그 특성상 항상 증가 혹은 감소하는 필드도 아니며 임의의 순서대로 들어오는 경우가 더 많으며, PK 필드는 대부분의 검색이 equal 비교이지, range(범위) 검색이 아니다. 따라서 대부분의 PK는 클러스터 인덱스로 설정해서 별로 얻는 바가 없다 할 수 있다.

개발할 때 어떤 개념이나 방식을 사용하고자 한다면, 그것이 근거가 있는 것인지 항상 파악하려는 자세가 필요하다. 카피캣(CopyCat)처럼 남들이 맹신하는 방식으로 하면  결코 즐겁지 못하다. 속도가 도리어 떨어지는 최적화를 해 놓고도, 델파이나 MS SQL의 버그라고 우기거나, 사서 고생하는 코딩 즉 삽질지수 어마어마한 코딩을 하게 될수도 있기 때문이다.

개발에서 떠도는 오래된 경험자들의 속담이 있다.

"쓸데없이 많이 아는 체 하려 하지 말고 하나라도 제대로 이해하고 사용하도록 노력하라!"

http://cafe.daum.net/delphinegong
최진용 [cjng96]   2008-10-07 09:41 X
생각해보니까 말씀하신 세번째 속설을 저도 별 생각없이 맞다고 생각하고 있었네요. 좋은 가르침 감사합니다. :)
아제나 [azena]   2008-10-07 11:06 X
저는 부두 프로그래머였군요 :)

본문과 관련해서 대부분의 프로그래머들이 pk를 별 의미가 없는 seq 같은 정보로 하는 경우가 많기 때문에 clustered로 하는게 낫다라는 말이 나온게 아닐까 싶네요.

+ -

관련 글 리스트
15167 MS SQL 서버의 Clustered (클러스터) 인덱스에 대한 그릇된 이해. 주정섭 6317 2008/10/06
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.