전문가칼럼

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (하)

전문가칼럼
DBMS별 분류
Oracle
작성자
dataonair
작성일
2014-10-01 00:00
조회
16817




◎ 연재기사 ◎


물탱크 구조로 알아본 오라클의 블록 옵션 ‘PCTFREE와 PCTUSED’


이산가족 찾기 생방송을 통해 배우는 DB 원리


개발자에게 맞는 DB 공부방법 찾기: 물리적 분류와 논리적 분류 그리고 인덱스


데이터베이스 인덱스의 오해와 진실


쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (상)


쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (하)


누구도 알려주지 않았던 ‘오라클 인덱스 생성도’의 비밀


누구도 알려주지 않았던 ‘오라클 쿼리 작성의 비법’


퀴리 최적화 및 튜닝을 위한 오라클 공정쿼리 작성법


만능 쿼리와 한 방 쿼리


오라클 옵티마이저 ‘CBO와 RBO’ 이해하기


재미있는 DB 이야기 ‘60갑자와 쿼리’


그림으로 배우는 ‘오라클 조인의 방식’ 이야기


반드시 알아야 하는 오라클 힌트절 7가지


오라클 플랜을 보는 법


개발자들의 영원한 숙제 ‘NULL 이야기’


알면 유용한 오라클 기능 ‘GATHER_PLAN_STATISTICS’


알면 유용한 오라클 기능들


오라클 DICTIONARY를 활용한 DB툴 프로그램 ‘FreeSQL’


이제는 말할 수 있다: 주식 자동매매 프로그램(상)


이제는 말할 수 있다: 주식 자동매매 프로그램(하)


개발자들이 자주 접하는 오라클 에러 메세지


재미있는 DB 이야기 ‘사라진 날짜를 찾아라’


오라클 랜덤 함수와 사용자 정의 함수


그림으로 배우는 ‘공정쿼리와 인덱스 생성도’


이병국의 개발자를 위한 DB 이야기: 디폴트 세팅의 함정과 오라클 파라미터


재미있는 DB 이야기 ‘놀라운 마방진의 세계’


오라클 운반 최소 단위 BLOCK


이병국의 개발자를 위한 DB 이야기: 이세돌과 알파고의 세기의 대결


이병국의 개발자를 위한 DB 이야기(30회) : DB 엔지니어의 가볍게 읽는 세상 이야기


이병국의 개발자를 위한 DB 이야기: 튜닝(31회) : 개발자를 위한 DB 튜닝 실전(1편)


이병국의 개발자를 위한 DB 이야기: 튜닝(32회) : 개발자를 위한 튜닝 실전(2편)


이병국의 개발자를 위한 DB 이야기: 튜닝(33회) : 개발자를 위한 튜닝 실전(3편)


이병국의 개발자를 위한 DB 이야기: 튜닝(34회) : 개발자를 위한 DB 튜닝 실전(4편)


이병국의 개발자를 위한 DB 이야기: 튜닝(35회) : 개발자를 위한 튜닝 실전(5편)


이병국의 개발자를 위한 DB 이야기: 페이징 처리에 대한 이해 (36회)


보기 좋은 떡이 먹기도 좋다 - 좋은 쿼리 좋은 성능


테이블의 수직분할과 수평분할에 대한 이해


DB 성능 제고를 위한 채번의 이해와 방식별 장단점 비교


이병국의 개발자를 위한 DB 이야기: 마지막회 : ‘개발자를 위한 DB 이야기’ 연재를 마치며



이병국의 개발자를 위한 DB 이야기: 인덱스 (6회)

쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (하)



이병국 andongcn@dreamwiz.com 프리랜서 DB 엔지니어로서 동아제약 전산실에서 SW 개발 업무를 시작으로 프리랜서 개발자로 독립해 활동하던 중 우연한 기회에 DB와 인연을 맺게 됐다. 현재 삼성생명 전산 운영팀에서 쿼리 성능을 개선하는 DB 튜닝과 IOA 업무를 맡고 있다. 개발자 출신의 DB 엔지니어로 활동하면서 개발자에게 DB 관련 지식이 꼭 필요함을 절감했다. ‘정보의 불균형이 시장 왜곡을 가져온다’는 ‘레몬시장이론’은 중고차 거래에서 흔히 나타나기 쉽다. 좋은 차와 나쁜 차를 아는 중개인과 모르는 구매자 사이에는 정보의 비대칭 때문에 구매자가 손해를 볼 수 있다. 구매자도 차에 대해 기본적인 지식을 알고 있어야, 정보의 균형이 맞으므로 서로 손해를 보지 않고 합리적인 가격에 차를 거래할 수 있다. 마찬가지로 개발자들도 DB에 대해 기본적인 지식을 습득하여 정보의 균형을 맞추면, DB 엔지니어와 협업이 더 쉬워지고 한 단계 더 발전한 자신의 모습을 발견할 것이다.

성공과 실패의 경험을 나누자, 용기와 희망을 나누자
개발업무를 시작으로 IT계에 입문했던 필자가 10년 가까이 DB 엔지니어로서 활동하면서 얻은 경험과
지식을 나누고자 한다. DB를 자주 접하는 SW 개발자뿐 아니라, DB 전문가를 꿈꾸는 대학생에서 DB 분야에
입문한 지 1~2년 된 기 입문자가 쉽게 이해할 수 있도록 비유를 통해 쉽게 접근해볼 계획이다.
물론 전문가들이라도 다시 한번 개념을 정립하는 의미에서 필요한 내용이 될 수 있다.
전체적으로 DB의 기본 원리와 개념을 이해하고 테이블, 인덱스, 쿼리, 튜닝, 플랜 등 개발자들이
알아야 하는 DB 전분야에 대해 쉽게 이해하도록 설명하겠다. DB 기술서적이나 번역서보다는
조금 더 부드럽게 접근할 계획이다. 그렇다고 흔히 서점에서 만날 수 있는 개발자 위주의
SQL 소개서도 아니다. 이 연재는 시리즈로 나갈 것이다.
연재를 끝까지 읽는 독자라면, 준전문가 수준의 DB 원리를 아는 것을 목표로 한다.

지난 연재에서 ‘인덱스 대상 후보 컬럼 선정 기준’에 대해서 자세히 살펴보았다. 계속해서 이번 연재에서도 인덱스 기본 원리들에 대한 추가적인 내용을 살펴본다.

인덱스 수는 적정해야 한다

테이블은 분류 대상을 갖고 있고 인덱스는 분류 정보를 갖고 있다. 만약 우리가 필요로 하는 분류 정보가 하나만 있어도 된다면 굳이 테이블과 인덱스가 분리되어 따로 존재할 필요는 없다. 테이블 그 자체에서 분류가 이루어 지면 되기 때문이다. 분류 대상과 분류 정보가 하나의 물리적 공간에 같이 존재한다면, 우리는 오직 하나의 분류만 가능하다. 하지만 우리는 분류 대상(테이블)에 대한 다양한 분류 정보(인덱스)가 필요로 하기 때문에 대부분의 DB에서 테이블과 인덱스는 분리되어 관리되고 있다.

결국 오라클에서 테이블은 분류 대상만을 가지게 되었고, 인덱스는 분류 정보만을 가지게 되었다. 테이블과 인덱스는 1:N의 관계에 있으며 인덱스는 테이블에 종속적이다. 테이블이 삭제되면 인덱스는 자동으로 삭제된다. 반면에 테이블과 뷰는 종속적인 관계가 아니다. 그래서 테이블이 삭제 되어도 뷰는 결코 삭제되지 않는다.

그렇다면 하나의 테이블에 종속적인 관계인 인덱스의 개수는 적어야 좋을까, 많아도 괜찮을까 인덱스의 개수가 많으면 많을수록 처리(Insert, Update, Delete)에서 많은 부하가 발생할 것이다. 그대신 조회(Select)에서는 빠른 결과를 볼 수 있다. 일반 DB 서적에서는 가능하면 최소한으로 만들어야 한다는 내용들이 많이 있고, 블로그 등을 살펴보면 하나의 테이블에 3~5개 정도의 인덱스가 적정하다고 주장하는 이들도 많다. 물론 타당한 내용이기도 하지만, 필자가 생각하기엔 테이블의 성격에 따라서 접근하는 것이 좋을 것 같다. 만약 테이블의 성격이 처리성 테이블이라면 가능한 적게 만들어야 할 것이며, 반면에 조회성 테이블이라면 많이 만들어도 부담이 없을 것이다.

우리는 아래와 같이 테이블을 분류할 수 있고, 해당 테이블의 성격에 맞게 인덱스를 만들 수 있다.

1. 코드성 테이블: 필요한 만큼 인덱스 생성 가능(인덱스 경합이 발생하지 않도록 주의)
2. 처리성 테이블: 최소한으로 사용(대용량 테이블이라면 가능한 한 적게)
3. 집계성 테이블: 필요한 만큼 적정하게 사용
4. 로그성 테이블: 필요 없음(필요에 따라서 하나 정도는 존재할 수도 있음)

첫 번째, 코드성 테이블인 경우 처리성 테이블이라기 보다는 조회성 테이블에 가깝다. 테이블 생성 초반에 필요로 하는 데이터가 적재될 가능성이 많으며, 수시로 변화하거나 추가되는 일은 별로 없는 테이블이다. 따라서 처리에 대한 부담이 없으므로 우리는 필요한 만큼 만들어서 사용하면 된다. 너무 인덱스 개수에 연연하지 않고 부담 없이 만들어서 사용하면 될 것이다. 단, 비슷한 인덱스가 생성된다면 인덱스 경합이 발생하므로 그 부분만 주의하면 될 것이다.

두 번째, 처리성 테이블인 경우 인덱스가 많을수록 부하가 많이 발생할 것이다. 처리성 테이블의 성격은 동사적인 성격을 가지고 있다. 예를 들면 쇼핑몰에서 주문 테이블(주문하다), 보험회사에서 계약 테이블(계약하다), 커뮤니티의 게시판 테이블(게시하다) 등. 이런 동사적인 성격을 가지고 있는 처리성 테이블은 조회(Select)보다는 처리(Insert, Update, Delete)에 더 많은 비중이 있는 테이블이므로 가능한 한 인덱스 개수를 최소화해야 한다.

세 번째, 집계성 테이블은 대부분 데이터 적재가 야간 배치에서 발생하는 경우가 많은 테이블이다. 처리에 대한 부담보다는 조회에 비중이 있는 테이블이므로 인덱스가 많아도 무방하다. 네 번째, 로그성 테이블은 조회의 비중이 거의 없는 테이블이다. 따라서 인덱스가 없는 경우가 대부분이며 필요에 따라 PK 정도는 있을 수 있다. 그 해당 PK도 데이터 추적에 용이한 시간의 정보를 가지고 있는 컬럼이면 충분할 것이다.

개발자가 필요로 하는 인덱스 요청에 대해 DBA는 몇 개 이상은 절대 안된다며 일률적인 숫자로서 강제하기보다는, 위의 4가지 테이블의 성격에 따라서 적절한 개수의 인덱스 생성을 지원하는 것이 좋을 듯 하다. 반면 인덱스는 정부의 규제와도 같다. 만들기는 쉬워도 삭제하기는 어렵다. 만들기 전에 반드시 필요한 것인지 충분하게 고민해야 한다. 인덱스는 가능하면 적게 만들어서 사용 할수록, DB 서버에 부하가 적다는 것은 자명하다. 만약 해당 테이블에 인덱스가 너무 많다면, 아래와 같은 내용도 인덱스 생성 여부를 결정하는 요소가 될 수 있다.

1. 쿼리 구동 시간이 낮인지 밤인지에 따라서 인덱스 생성 여부를 결정할 수 있다(온라인, 배치).
2. 누가 사용하는지에 따라서 인덱스 생성 여부를 결정 할 수 있다(담당자, 관리자, 사장).
3. 얼마나 많이 구동되는지에 따라서 인덱스 생성 여부를 결정할 수 있다.

추가적으로 한가지 덧붙인다. 테이블의 크기가 수백 바이트 이내이거나 데이터 건수가 수백 건 이내인 소형 테이블인 경우 인덱스가 필요 없다고 주장하는 이도 있는데, 일면 맞는 면도 있지만 반드시 그렇지는 않다. 그 정도 규모의 테이블이라면 대부분 코드성 테이블인 경우가 많다. 코드성 테이블에 있는 인덱스는 조건절에 사용되기 보다는 조인절에 사용되는 경우가 더 빈번하다. 조건절 보다는 조인절에 사용하는 인덱스가 더 중요하다고 필자는 생각한다. 뒤에 다시 한번 자세히 언급되어 있다. 또한 인덱스가 없어서 플랜에서 Full Scan이 보이면 튜닝 전문가는 멈칫하고 긴장한다. 튜닝 전문가 입장에서는 긴장감 없이 일관성 있게 플랜이 좋게 보이길 원할 것이다. 소형 테이블이므로 인덱스가 없어도 얻는 이익이 거의 없지만, 인덱스가 있어도 크게 부하를 걱정할 이유는 없다. 이런 여러 가지 이유로 인하여 필자는 아주 규모가 작은 테이블이라도 인덱스는 있어야 한다고 말하고 싶다.



인덱스는 위치정보와 순서정보로 구성됐다

지난 연재에서 인덱스는 위치(조건) 정보와 순서(SORT) 정보의 특성을 가지고 있다고 이미 말하였다. 인덱스는 도서의 목차나 색인의 역할처럼 빨리 찾는 의미로 많이 인식되기도 하지만, 인덱스는 기본적으로 위치(조건) 정보와 순서(SORT) 정보의 특성을 동시에 가지고 있는 분류 정보이기도 하다. 데이터베이스의 인덱스와 마찬가지로 분류에도 위치정보와 순서정보를 가지고 있다. 대형할인매장에서 우유를 찾아보자. 일단 식품코너를 찾을 것이며, 수많은 식품 코너에서 우유가 진열된 곳을 찾을 것이다. 또한 본인이 좋아하는 특정 브랜드 우유를 찾을 것이다. 우리는 이미 알고 있는 위치정보로 여기까지 찾아왔다. 과연 우리가 원하는 최종 목적지까지 왔는가

동일한 브랜드 우유라도 우리는 가장 최근에 제조된 우유를 원할 것이다. 식품코너 분류 담당자가 제조일자(ASC)로 분류 할지라도 여러분은 제조일자(DESC)로 찾을 것이다. 필자는 인덱스가 목차나 색인처럼 축소된 역할의 의미로 인식되기 보다는 좀 더 광범위한 분류의 의미로 인식되기를 바라고 있다.

WHERE 구획 = ‘식품코너’
AND 제품 = ‘우유’
ORDER BY 제조일자 DESC

위의 쿼리에서 ‘구획’ 컬럼과 ‘제품’ 컬럼은 위치(조건) 정보를 갖고 있고, ‘제조일자’ 컬럼은 순서(SORT) 정보를 가지고 있다. 우리는 다음의 두 가지 경우의 인덱스를 검토할 수 있다.

인덱스 1 = 구획 + 제품
인덱스 2 = 구획 + 제품 + 제조일자(DESC)

두 가지 경우의 인덱스가 모두 가능하지만, 인덱스가 많을수록 DB에 부하가 증가하므로, 동시에 만들면 안 된다는 사실을 우리는 이미 알고 있다. 또한 인덱스에서 구성 컬럼의 수가 많을수록 부하도 많다는 것을 안다. 그러면 위의 두 가지 인덱스에서 어떤 인덱스를 생성할지 결정하는 기준은 무엇인가 일반적으로, CBO(Cost Based Optimizer) 에서는 조건에 따른 Get Block 비용(부하)보다 Sort의 비용(부하)이 몇 배 더 크다. 따라서 조건에 따른 데이터 결과 건수가 SORT 비용(부하)을 감내할 수 있다면 ‘인덱스 1‘이 좋을 것이고, 감내할 수 없다면 ‘인덱스 2’가 좋을 것이다.

사람마다 시스템마다 판단 기준이 다를 수 있으므로, 스스로 최적의 기준을 세우기 바란다. 필자는 다음과 같은 기준으로 결정을 하고 있다. 조건에 따른 데이터 결과 건수가 수백 건 단위라면 SORT에 부담이 없다고 판단하여 ‘인덱스 1’을 생성하고 수천 건 단위라면 SORT에 부담이 있다고 판단하여 ‘인덱스 2’를 생성한다. 물론 여기에는 해당 쿼리의 구동횟수에 따른 부하도 감안하여 결정한다.

WHERE 구획 = ‘식품코너’
AND 제품 = ‘우유’
AND 제조일자 BETWEEN ‘20140701‘ AND ‘20140707’
ORDER BY 제조일자 DESC, 제조번호 ASC

위의 쿼리에서 구획, 제품, 제조일자, 제조번호 컬럼은 인덱스 후보 컬럼이다. 만약 여러 개의 컬럼으로 인덱스를 생성하고자 한다면 고려해야 할 중요한 요소중의 하나가 바로 인덱스 컬럼의 순서이다. 다음의 규칙으로 인덱스 컬럼의 순서를 정하면 된다.

1. 위치정보 컬럼만으로 구성할 수 있다. 혹은 순서정보 컬럼만으로 구성할 수 있다.
2. 위치정보 컬럼과 순서정보 컬럼의 순으로 구성할 수 있다.
3. 위치정보 컬럼과 순서정보 컬럼의 순서는 혼재되어서는 안되며 뒤바뀌어서도 안된다.

구획: 위치정보 컬럼이다(‘=‘ 조건이므로…).
제품: 위치정보 컬럼이다(‘=‘ 조건이므로…).
제조일자: 위치정보 + 순서정보 컬럼이다(‘=“ 조건이 아니라 범위 조건이므로).
제조번호: 순서정보 컬럼이다(SORT 절에 있으므로).

따라서 위의 규칙을 적용하면 아래와 같은 인덱스를 구성할 수 있다.

인덱스 = 구획(위치) + 제품(위치) + 제조일자(위치+순서) + 제조번호(순서)

위의 인덱스는 위치정보 및 순서정보 컬럼으로 구성되어 있으며 순서정보 컬럼은 반드시 위치정보 컬럼의 후행에 있다는 것을 명심하자.



조건절에 사용하는 인덱스와 조인절에 사용하는 인덱스

인덱스는 조건절에서 사용되기도 하고 조인절에서 사용되기도 한다. 조건절에서 사용하는 인덱스는 최초로 접근하는 테이블을 결정하는 중요한 인덱스이며, 데이터 접근 범위를 줄여주는 역할을 한다. 조인절에서 사용하는 인덱스는 테이블간의 관계를 맺는 인덱스로서, 데이터 접근 범위를 항상 줄여주는 것은 아니다. 1:다 관계의 테이블 조인에서는 오히려 접근 범위가 커지기도 한다.

오라클 쿼리에서 테이블간의 관계를 연결해주는 조인의 방법에는 Nested Loop Join, Sort Merge Join, Hash Join 세 가지가 있는데 온라인 쿼리에서 우리가 접하는 대부분의 조인 방법은 Nested Loop Join이다. Nested Loop Join만으로 구성된 쿼리에서는 오로지 하나의 조건절 인덱스와 다수의 조인절 인덱스로 구성된다. 따라서 우리가 접하는 대부분의 쿼리에서는 조건절 인덱스가 최초로 접근하는 테이블을 결정한다고 해도 틀린 말은 아니다.

column_img_1477.jpg
<그림 1>

위의 <그림 1>에서 1번은 조건절에 인덱스가 없는 경우이고, 2번은 조인절에 인덱스가 없는 경우다. 조건절에 인덱스가 없는 것보다 조인절에 인덱스가 없는 것이 성능 면에서 더 치명적이다. 1번처럼 조건절에 인덱스가 없다면, 주문 테이블에 Full Scan이 한 번만 발생하며, 거기에서 얻어진 레코드 수만큼만 고객 테이블을 Index(Random Access)로 접근할 것이다. 만약 2번처럼 조인절에 인덱스가 없다면 어떻게 될까 테이블간 Join 방식에 따라서는 고객 테이블의 Full Scan이 한번 혹은 그 이상 발생할 수 있다. 결국 튜닝의 관점에서 본다면, 조인절에 인덱스가 없는 것이 더 성능 저하를 가져올 수 있다는 점을 우리는 잊지 말아야 한다.



인덱스 생성/삭제 시 고려사항

인덱스는 만들었다고 모두 이용되는 것도, 사용하지 않는다고 바로 삭제 가능한 것도 아니다. 인덱스는 만들 때나 삭제할 때나 언제나 신중하게 접근하는 것이 필요하다. 물론 불필요한 인덱스는 만들지도 말아야 하고, 사용하지 않는다면 인덱스를 삭제하거나 유사 인덱스끼리 통합을 해야겠지만, 여러 가지 발생 가능한 문제점에 대한 충분한 검토가 필요하다.

1. 신규 인덱스 생성하기 전에 유사 인덱스가 존재하는지 확인한다(꼭 필요한 인덱스인가)
2. 신규 인덱스 생성하기 전에 Index Split을 유발하지 않는지 확인한다.
3. 신규 인덱스 생성하기 전에 CBO 방식에서의 통계정보가 최신인지 확인한다.
4. 기존 인덱스 삭제하기 전에 사용하지 않는 미사용 인덱스인지 반드시 확인한다.



1번에 해당하는 경우를 간과한다면 유사한 인덱스끼리 경합이 발생할 수도 있고, 기존 쿼리의 플랜이 변동하여 성능상에 문제가 발생할 수 있어서 주의가 요구된다.

2번의 경우는 인덱스 분류 작업이 한곳으로 집중되어서, 동일한 Leaf Block에 대해 과도한 Split이 발생한다면 성능상의 문제가 발생할 수도 있기 때문이다. 더 쉬운 예를 든다면, 대규모 물류 창고에서 수많은 지게차가 카테고리에 맞게 물품을 분류할 것이다.
만약 지게차가 분산되지 않고, 분류 지역의 좁은 공간에 몰려서 특우와 같다. Split 발생하는 대표적인 컬럼으로는 등록일시와 같은 컬럼이며, 해결 방안으로는 Reverse Index를 이용할 수 있다.



3번의 경우는 인덱스를 생성할 테이블의 통계정보와 실제 정보간의 갭이 용인 가능한지 아닌지에 대한 문제이다. 급격하게 데이터가 증가하는 테이블에는 더욱더 확인이 필요하다. 만약 통계 정보와 실제 정보가 현격하게 차이가 난다면, 인덱스가 생성 되어도 이용되지 않을 가능성이 많다.

4번의 경우처럼 이미 만들어진 인덱스가 어떤 쿼리에서도 사용되지 않는다는 확신이 있어도 결코 삭제하기가 쉽지 않다. 우리가 모르는 어떤 배치 쿼리, 어떤 온라인 쿼리에서 실제로 사용하는 경우가 있을 수도 있다. 게다가 사용중인 인덱스를 잘못 삭제한 경우 발생할 사고의 가능성 때문에, 대부분의 DBA는 개발자의 인덱스 삭제 요청을 싫어한다. 솔직히 인덱스 생성 요청도 DBA에게는 부담이 된다.



결합 인덱스의 컬럼 순서 결정방법

하나의 컬럼으로 만들어진 인덱스는 단일 인덱스이고, 여러 컬럼으로 만들어진 인덱스는 결합인덱스라는 것은 알고 있을 것이다. 단일 인덱스에서는 컬럼의 분포도가 중요한 요소이지만, 결합 인덱스에서는 컬럼들의 순서가 중요한 요소이다. 물론 결합 인덱스도 각각의 컬럼은 분포도가 나쁠지라도 전체 컬럼의 분포도는 좋아야 하는 것은 당연하다.

결합 인덱스를 만들 때 우리가 가장 신경을 써야 하는 부분은 인덱스를 구성하는 컬럼의 순서 결정이다. 필자가 생각하는 결합 인덱스의 컬럼 순서 결정 방법은 아래와 같다.

1. 공통적으로 사용하는 필수 조건절 컬럼을 우선한다.
2. ‘=‘ 조건의 컬럼을 다른 연산자 컬럼 보다 우선한다.
3. 대분류 중분류 소분류 컬럼순으로 구성한다.
4. 위치(조건) 정보 컬럼은 순서(SORT) 정보 컬럼보다 우선한다.

위의 4가지 방법으로 결합 인덱스의 컬럼 순서를 결정할 수 있으며, 각각의 방법간에는 우선 순위가 없으며 복합적으로 종합 판단하여 결정 되어야 할 것이다.

분포도가 좋은 컬럼은 처리 범위를 줄여 주기 때문에 결합 인덱스의 선행 컬럼으로 사용해야 한다고 다수의 블로그에서 인용하기도 하지만, 이것은 옳지 않다. 분포도가 좋은 컬럼을 선행으로 할 때와 후행으로 할 때의 Get Block 을 실제로 비교하면, 그 값은 별로 차이가 없다. 분포도가 좋은 컬럼을 선행으로 해야 하는 명확한 이점은 없다. 이미 지난 연재에서 이 부분에 대해 자세히 설명했으니 참고하기 바란다.

이것으로 인덱스 기본 규칙에 대한 전반적인 설명을 마무리 하며, 다음 연재에서는 인덱스 생성도에 대해 소개하겠다. 필자가 전체 연재에서 가장 중요하게 생각하는 몇 안 되는 부분이기도 하고 실제 개발자에게 꼭 필요한 부분이기도 하다. 인덱스 생성도라는 용어는 실제로 존재하지는 않는다. 필자가 나름 정의해 사용하는 말이다.

지금까지 만나본 대부분의 개발자는, 복잡한 실제 쿼리에서 인덱스를 만들어야 하는 정확한 포인트를 잘 알지 못했다. 물론 필자도 초보 개발자일 때는 잘 몰랐다. 수년간의 경험과 노하우로 쿼리에서 인덱스를 만들어야 하는 포인트를 쉽게 아는 방법을 체득했다. 그것이 바로 인덱스 생성도다. 다음 연재에서는 인덱스 생성도에 대해서 집중적으로 설명하겠다.



용기를 갖자
오라클 DB뿐 아니라 대부분의 DB 구성 알고리즘은 어느 날 ‘하늘에서 뚝 떨어져 새로 만들어진 것’이 아니라
실생활에서 이용되는 혹은 이미 상식 수준에서 인지되는 그런 보편적인 원리를 바탕으로 만들어졌으므로
쉽게 접근하고 이해할 수 있다. 서두에서 말했듯이 ‘레몬시장이론’을 상기하며 DB를 지레짐작으로
어려워하지 말고 용기를 내고 하나씩 터득해 나가기를 바란다.
이 글은 DB 전문가 수준의 이해를 요구하지는 않는다. 단지 DB에 대해서 더 친숙하고 더 쉽게 이해하고
접근하길 바랄 뿐이다. 이 글을 읽으면서 궁금하거나 의문 나는 점이 있으면, 댓글을 달아주실 것을 적극 바란다.
아무리 어렵고 힘든 일이더라고 ‘관계’와 ‘소통’으로 풀어나갈 수 있음을 다시 한 번 믿으며...

[지난 문제의 정답과 풀이]

원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제



지난 연재에 출제한 ‘원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제’에 대한 정답과 해설은 아래와 같다. 문제를 풀면서 DB 원리를 하나씩 배우고 이해 할 수 있다.

column_img_1478.jpg

정답 : 테이블 접근 순서는 A -> B -> E -> D -> C / 인덱스 생성 포인트는 1, 3, 8, 11, 5

해설 : 테이블 접근 순서는 첫번째 진입 테이블에서부터 자연스럽게 조인절을 따라가면 된다. 단, Inner Join 이 Outer Join 보다 우선 한다는 것만 잊지 말자. 그러므로 테이블A로 진입하여 조인절을 따라 B, E, D 테이블로 접근하며, C 테이블은 Outer Join 이므로 마지막으로 접근한다.인덱스 생성 포인트는 항상 목적지(target) 테이블의 컬럼에 존재하면 된다. 우편배달부가 편지를 배달할 때 출발지 주소는 중요하지 않으며 오로지 목적지 주소만 중요하듯이 인덱스 생성 포인트도 항상 목적지 테이블의 컬럼에만 존재하면 된다. 그래서 1, 3, 8, 11, 5 컬럼이 인덱스 생성 포인트다.



[이번 호 문제]

원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제



각 연재의 말미에 간단하고 재미있는, 생각해 보는 문제를 출제하려 한다. 모든 문제는 DB의 원리를 이해할 수 있는 문제로 출제할 예정이다. 문제를 풀면서 DB 원리를 하나씩 배우고 이해할 수 있다. 정답과 그에 대한 설명은 다음 연재에서 한다.



column_img_1479.jpg