# Index(색인)이란 무엇일까? 

- Index란 주로 책의 첫 장에 있는 "목차"에 비유된다. 

 

# 이걸 왜 사용하는걸까? 

자, 사전을 펼쳤다고 생각해보자.

"한글" 이라는 단어에 관한 내용을 찾아보려고 한다.  어떤 방법으로 찾는게 빠를까?

 

1. 목차를 보고 'ㅎ' 으로 시작하는 단어의 페이지를 펼친 후 찾는다.

2. 책의 처음부터 끝까지 "한글"이라는 단어를 찾는다.

 

정답은 당연히 1번이다. 

 

이와 같이 방대한 양의 데이터 중 내가 원하는 데이터를 빠르게 찾기 위해서 

Index를 사용한다고 생각하면 된다. 

 

# 그럼 우리는 Index를 어떻게 설정하고 사용할까? 

table을 설계하다보면 index를 지정하기 위해 고민이 필요하다. 

index로 최대한 효율을 뽑아내려면 내가 지정한 index로 최대한 많은 데이터를 걸러낼 수 있어야한다. 

 

그러기 위해 우리는 카디널리티(Cardinality)가 가장 높은 컬럼을 index로 지정해주어야한다. 

 

*카디널리티(Cardinality) - 컬럼의 중복된 수치를 나타낸다. ( 상대적인 개념으로 이해하면 된다.)
회원관리에서 성별은 주민등록번호에 비해 중복된 데이터가 많다 -> 이 경우 카디널리티가 "낮다"
반면, 주민등록번호, 휴대폰 번호는 성별에 비해 중복된 데이터가 적다 -> 카디널리티가 "높다" 

 

 

회원정보 테이블에서 index로 성별을 지정하게 된다면 데이터의 50% 밖에 걸러내지 못함. ( 성별비율 5:5 가정 ) 

하지만 중복된 데이터가 없는 주민번호로 걸러낸다면 훨씬 빠른 검색이 가능할것이다. 

 

그러니 index를 설정할땐 가장 중복되지 않는 값을 인덱스로 정하는게 좋다. (= 카디널리티가 높은)

( 단, index의 길이가 길면 길수록 성능에 이슈가 있으니 짧은걸로 잡는게 좋다. )

 

 

# 여러개의 Index를 설정하려고 하는데 어떤 순서로 구성해야할까? 

여러개의 index를 설정하면 어떤 순서로 구성하는게 좋을까

 

1. 카디널리티가 낮은 -> 높은 

2. 카디널리티가 높은 -> 낮은

 

간단한 예를 들어 생각해보자. 

예) 전국민의 정보가 들어있는 DB에서 서울시에 거주중인 100세 여성 인구수를 조사한다. 

 

1. 카디널리티가 낮은 -> 높은 

- 여성으로 거른다. --> 2500만명

- 서울시에 거주중인 사람으로 거른다. --> 800만명

- 나이가 100인 사람으로 거른다 --> 1만명

( SELECT * FROM 전국민 WHERE 성별 ='여성' AND 거주지 = '서울' AND  나이 = 100; )

 

2. 카디널리티가 높은 -> 낮은

- 나이가 100인 사람으로 거른다. --> 10만명 

- 서울시에 거주중인 사람으로 거른다.  --> 2만명

- 성별을 여성으로 거른다. --> 1만명 

( SELECT * FROM 전국민 WHERE 나이 = 100 AND 거주지 = '서울' AND 성별 ='여성'; )

 

위 조건을 보면 어떤식으로 걸러내는게 빠를지 알 수 있다. 

실제 쿼리의 동작에서도 예시와 같이 카디널리티가 높은순에서 낮은순으로 구성하는것이 성능이 좋다. 

 

 

# 주의 사항 

- Index를 지정했다고해서 모두 사용해야만 하는 것은 아니다. 

그렇다면 지정한 Index 중 누락되어도 되는것과 누락되면 안되는 것은 어떤 걸까

 

# 누락되면 안되는 index 

- index 설정을 아래의 순서로 지정했다고 한다면 

 (인덱스 ::::   나이 > 거주지 > 성별 )

 

SELECT * FROM 전국민 WHERE 거주지 = '서울' AND 성별 ='남성'; 

-> 이렇게 조회하는 경우 인덱스가 적용되지 않는다.

내가 설정한 첫번째 인덱스인 "나이"가 조건에 포함 되어 있는 경우만 다른 인덱스의 적용이 가능하다. 

 

SELECT * FROM 전국민 WHERE  나이 = 50 AND 성별 ='남성';  ==> index 적용 O. 

 

 

# 인덱스에 범위 조건을 지정하는 경우 어떤일이 생길까 

SELECT * FROM 전국민 WHERE 나이 > 99 AND 거주지 = '서울' AND 성별 = '남성'; 

 

위 쿼리를 조회를 한다면 나이까지는 적용이 되지만 거주자와 성별은 Index가 적용되지 않는다. 

- 즉  between, like, <, > 등 범위 조건을 사용하면 뒤에 오는 인덱스가 사용되지 않는다고 생각하면 된다. 

 

반면에 

 =, in은 다음 컬럼도 index가 적용된다. ( in 은 결국 = 를 여러번 실행한 것이기 때문)

 단, in 인자값으로 서브쿼리를 넣게되면 성능상 이슈가 발생할 수 있는데

 이유는 서브쿼리의 외부가 먼저 실행되고 in 은 체크 조건으로 실행되기 때문이다.

 

 

# AND 와 OR  연산시 주의사항 

AND는 조회할 ROW 수를 줄이는 역할을 하지만 OR 연산자는 비교해야할 ROW가 늘어나기 때문에 

풀 테이블 스캔이 발생할 확률이 높다. 그러니 사용할 때 주의하기. 

 

 

# Index로 설정한 컬럼값 그대로 사용해야 인덱스가 적용된다. 

- WHERE 나이 +10 > 10 ==>  X 

- WHERE 나이 > 10 * 2  ==>  O

 

 

# Index 조회 순서 

- 요즘은 예전처럼 꼭 index의 순서와 조회 순서를 지킬 필요는 없다고한다. 

  중요한건 Index 컬럼들이 조회 조건에 포함되있는것이다.

 

 

 

 

끝===

공부를 위해 찾아본 내용이라 오류가 있을 수 있습니다. 

틀린 부분이 있다면 댓글로 남겨주시면 감사하겠습니다 ^^. 

 

 

 

 

참고

http://www.mysqlkorea.com/sub.html?mcode=manual&scode=01&m_no=21436&cat1=7&cat2=0&cat3=0&lang=k

https://webmonkeyuk.wordpress.com/2010/09/27/what-makes-a-good-mysql-index-part-2-cardinality/

'프로그래밍' 카테고리의 다른 글

톰캣과 아파치를 같이 사용하는 이유는 무엇일까?  (0) 2020.09.11
단축 URL ( URL Shortener ) 원리와 사용법  (0) 2020.08.20
File Download  (0) 2020.08.17
IP 개념 정리!  (0) 2020.08.13
OOP 5대 원칙 (SOLID)  (0) 2020.07.13

+ Recent posts