로직과의 사투/DB

쿼리튜닝 겉핥기 - 인덱스의 사용 (MySQL위주)

MySQL 공식 도큐먼트의 설명에 의하면 SELECT절의 성능을 향상시키는 가장 좋은 방법은 하나 또는 하나 이상의 컬럼의 인덱스를 만들어 주는 것으로 언급하고있다. 그렇기 때문에 어떤 컬럼을 인덱스화 시키고 어느 구절에 인덱스 컬럼을 사용하는 것이 좋은지 잘 파악하고 사용하는 것이 중요할 것이다. 인덱스는 특정 Columns에 맞는 Rows 찾을 때 사용 된다. 만약 인덱스가 없다면 MySQL에선 첫 행 부터 쭉 읽으며 전체 테이블을 훑을 텐데, 이는 테이블이 커지면 커질 수록 그 비용이 증가하는 현상을 초래한다.

1.  WHERE 절에서의 인덱스 사용

인덱스를 사용의 이유를 가장 손쉽게 깨달을 수 있는게 WHERE 절에 사용되는 Columns가 아닌가 싶다. 그러나 WHERE 절에 사용되는 컬럼을 무조건 Index 건다고 좋은 것은 아니다. WHERE절에 범위 조건이 있는 컬럼을 사용해야 인덱스를 제대로 탈 수 있다. 범위 조건은 값이 크다, 작다, 크거나 같다, 같다와 같은 비교문을 뜻하며 만약 범위 조건이 없다면 옵티마이저는 테이블 순차 스캔을 시도할 것이다. 또한, <>, != 와 같은 부정형 조건이나 NULL비교는 인덱스를 사용할 수 없다. 인덱스의 컬럼을 조건절에서 가공해 사용할 때에도 인덱스를 사용할 수 없다. 그렇기 때문에 이러한 쿼리는 쿼리 자체를 튜닝 해주어야 한다.

2. 카디널리티(Cardinality)가 높은 컬럼에 인덱스 사용

카디널리티(Cardinality)란 전체 행에 대한 특정 컬럼의 중복 수치를 나타내는 지표이다. 여기서 컬럼의 중복도가 낮으면 카디널리티가 높은게 되고 컬럼의 중복도가 높다면 카디널리티가 낮다고 표현된다. 인덱스를 생성해야 할 때 이 카디널리티를 참고해서 인덱스를 생성하면 좋다. 예를 들어 대한민국 국민 테이블이 있다고 가정했을 때 주민등록번호의 값은 카디널리티가 '높다' 고 표현할 수 있다. 그와 반대로 성별, 이름과 같은 컬럼은 중복 데이터가 존재하기 때문에 주민등록번호에 비해 상대적으로 카디널리티가 낮다고 표현할 수 있다. 또한 여러 칼럼을 인덱스로 생성해야하는 경우 카디널리티가 높은 순에서 낮은 순으로 구성하는 것이 좋다. 카디널리티가 높은 순으로 필터링 하여 조회하기 때문이다. 여기서 말한 카디널리티는 약간 정성적 수치의 카디널리티로 이해했다.

MySQL에서 한 Index의 정량적 수치의 카디널리티를 확인하는 방법은 SHOW INDEX FROM '테이블명'으로 조회하면 해당 테이블 인덱스 정보들을 조회할 수 있다.

3. 테이블 조인을 위해 연결고리로 자주 사용되는 컬럼

조인 쿼리에 사용되는 컬럼의 경우 풀스캔을 타게 되면 조인의 수가 늘어날 수록 풀스캔하는 데이터 수가 많아지므로 병목현상의 대표적인 원인이 된다.

4. 인덱스를 사용시 주의할 점.

인덱스를 사용할 때 주의할 점은 상당히 많다. 인덱스를 만드는 것 자체가 MySQL의 리소스를 차지하기도 하고 필요없는 인덱스가 많을 수록 MySQL의 옵티마이저가 어떤 인덱스를 선택해야 하는 지 결정하는 것에도 리소스를 잡아먹힌다. 또한 인덱스가 걸린 컬럼의 Insert, Update, Delete의 동작이 발생시 Index 데이터 역시 같이 업데이트 되어야 하기 때문에 Insert, Update, Delete 의 비용을 증가 시킨다. 그렇기 때문에 Index로 활용될 컬럼을 전략적으로 잘 선택해 알맞은 손익분기점을 찾아내야한다. 

5. 정리

간략하게 인덱싱까지 정리해보았으나 이해가 잘 되지 않는 부분도 많고 애매한 설명이 많은 것 같다. 그렇기 때문에 틀린 부분도 많을 것 같다. DB 관련 내용은 더욱 공부를 철저하게 해서 작성한 글들을 수정 작업하거나 완전 재작성이 필요해 보인다...

참고 문서)
https://dev.mysql.com/doc/refman/8.0/en/optimization-indexes.html

https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html

https://d2.naver.com/helloworld/1155

https://yurimkoo.github.io/db/2020/03/14/db-index.html

'로직과의 사투 > DB' 카테고리의 다른 글

쿼리튜닝 겉핥기 - 인덱스란?  (0) 2021.05.24
쿼리튜닝 겉핥기 - 개요, 옵티마이저  (0) 2021.05.19