어댑티브 해시 인덱스
일반적으로 '인덱스'라고 하면 흔히 사용자가 생성한 B-Tree 인덱스를 떠올릴 것이다.
반면, 어댑티브 해시 인덱스는 사용자가 수동으로 생성하는 인덱스가 아니라 InnoDB 스토리지 엔진에서 사용자가 자주 요청하는 데이터에 대해 자동으로 생성하는 인덱스이다.
어댑티브 해시 인덱스는 innodb_adaptive_hash_index 시스템 변수를 이용해 기능을 활성화할 수 있다.

흔히 우리가 알고 있는 B-Tree 인덱스는 특정 값을 찾기 위해 루트 노드를 거쳐 브랜치 노드, 리프 노드까지 찾아가야 원하는 레코드를 읽을 수 있다. 따라서 이러한 B-Tree 인덱스는 자주 사용되는 데이터라도 매번 B-Tree를 타야한다는 아쉬운 부분이 있다.
어댑티브 해시 인덱스의 성능 향상

어댑티브 해시 인덱스는 이러한 B-Tree의 검색 시간을 줄여주기 위해 도입된 기능이다.
InnoDB 스토리지 엔진은 인덱스 키 값과 인덱스 키 값이 저장된 데이터 페이지 주소의 쌍으로 어댑티브 해시 인덱스를 만들어 관리하고, 필요할 때마다 어댑티브 해시 인덱스를 사용해서 레코드가 저장된 데이터 페이지를 즉시 찾아갈 수 있다.
이로 인해 B-Tree를 타는 비용이 없어지므로 쿼리의 성능을 향상시킬 수 있게 된다.
어댑티브 해시 인덱스에서 인덱스 키 값은 'B-Tree 인덱스의 고유 번호(Id)와 B-Tree 인덱스의 실제 키 값'의 조합으로 생성된다.
B-Tree 인덱스의 고유 번호가 포함되는 이유는 InnoDB 스토리지 엔진에서 해시 인덱스는 하나의 객체로 존재하므로, 모든 B-Tree 인덱스에 대한 어댑티브 해시 인덱스가 하나의 해시 인덱스에 저장된다. 따라서 특정 키 값이 어느 인덱스에 속한 것인지도 구분해야 하기 때문에 B-Tree 인덱스의 고유 번호가 포함된다.
여기서 유의할 점은 어댑티브 해시 인덱스가 가리키는 데이터 페이지의 주소는 InnoDB 버퍼 풀에 로딩된 페이지의 주소를 의미한다는 것이다. 따라서 어댑티브 해시 인덱스는 버퍼 풀에 올려진 데이터 페이지에 대해서만 관리된다는 점을 알고 가야 한다.
InnoDB 버퍼 풀은 디스크의 데이터 파일이나 인덱스 정보를 메모리에 캐시해두는 공간으로, 쓰기 작업을 지연시켜 일괄 작업으로 처리할 수 있게 해주는 버퍼 역할도 한다.
어댑티브 해시 인덱스가 보여줄 수 있는 성능 효과는 아래와 같다.
CPU 사용률
쿼리 처리량
이미지 출처: kakao Tech(MySQL InnoDB의 Adaptive Hash Index 활용)
위 지표를 보면 쿼리의 처리량은 2배 가까이 늘었고, CPU 사용률은 오히려 떨어진 것을 알 수 있다. 또한 어댑티브 해시 인덱스로 인해 B-Tree 탐색이 줄면서 InnoDB 내부 잠금 횟수도 줄어들게 된다.
추가적으로 예전 버전까지는 어댑티브 해시 인덱스가 하나의 메모리 객체이기 때문에 이에 대한 경합이 심했는데, MySQL 8.0부터는 내부 잠금에 대한 경합을 줄이기 위해 파티션 기능이 도입되었다.
innodb_adaptive_hash_index_parts 시스템 변수를 이용해 파티션 개수를 변경할 수 있다.
그렇다면 어댑티브 해시 인덱스는 항상 좋은 것인가?
어댑티브 해시 인덱스는 데이터 페이지를 버퍼 풀 내에서 접근하는 것을 빠르게 만드는 기능이기 때문에 데이터 페이지를 디스크에서 읽어오는 경우가 빈번하다면 도움이 되지 않는다.
또한 어댑티브 해시 인덱스도 메모리를 사용한다는 점에 유의해야 하고, 어댑티브 해시 인덱스가 활성화되면 InnoDB 스토리지 엔진은 인덱스 키 값이 있든 없든 검색해봐야 하기 때문에 어댑티브 해시 인덱스의 효율이 없어도 계속 사용하게 된다.
그리고 어댑티브 해시 인덱스는 테이블의 삭제 작업에도 많은 영향을 미치는데, 만약 특정 테이블을 삭제하면 InnoDB는 해당 테이블이 가진 모든 데이터 페이지의 내용을 어댑티브 해시 인덱스에서 제거해야 한다. 이로 인해 테이블이 삭제되는 동안 많은 CPU 자원을 사용하게 되고, 그만큼 DB의 성능이 느려지게 된다.
따라서 어댑티브 해시 인덱스의 히트율, 어댑티브 해시 인덱스가 사용중인 메모리 공간, DB 서버의 CPU 사용률을 종합해서 어댑티브 해시 인덱스가 현재 서비스에 도움이 되는지를 잘 판단해서 사용해야 한다.
Reference
'DevOps' 카테고리의 다른 글
Jenkins를 활용한 자동 배포 구축 (0) | 2022.05.13 |
---|---|
인덱스 컨디션 푸시다운(index_condition_pushdown) (0) | 2022.02.19 |
도커 스웜(Docker Swarm) 알아보기 (0) | 2021.12.26 |
Docker란 무엇인가 (0) | 2021.12.20 |