InnoDB 알아보기 (In-Memory Structures - Adaptive Hash Index)

2024. 1. 31. 22:37Database

Adaptive Hash Index

일반적으로 인덱스(Index)라고 하면 사용자가 테이블에 생성한 인덱스(일반적으로 B-Tree 기반)를 의미한다.

InnoDB는 사용자가 생성하는 인덱스 외에 자주 요청되는 데이터에 대해 자동으로 인덱스를 생성하는데,

이를 어댑티브 해시 인덱스라고 한다.

 

어댑티브 해시 인덱스는 innodb_adaptive_hash_index 를 통해 활성화할 수 있다.

 

 

 

✔️ 등장 이유

B-Tree 인덱스에서 특정 값을 찾기 위해서는 루트 노드부터 시작하여 브랜치 노드를 거쳐 리프 노드로 도달해야 한다.

인덱스를 사용하지 않고 데이터를 찾는 것에 비해서는 빠르지만,

노드를 탐색하는 과정이 필요하므로 해시 기반 인덱스보다는 느리게 동작한다.

 

어댑티브 해시 인덱스는 B-Tree 인덱스의 검색 시간을 줄여주기 위해 도입되었다.

이름에서부터 해시 기반의 인덱스임을 알 수 있는데,

원하는 데이터를 곧바로 찾을 수 있기에 B-Tree를 사용했을 때 보다 성능이 좋아진다.

 

 

 

✔️ 특징

어댑티브 해시 인덱스는 '인덱스 키 값'과 '데이터 페이지 주소'의 값으로 관리된다.

'인덱스 키 값'은 B-Tree 인덱스의 Id실제 키 값을 조합하여 생성된다.

 

어댑티브 해시 인덱스의 키 값에 B-Tree 인덱스의 Id가 포함되는 이유는,

InnoDB에서 어댑티브 해시 인덱스는 하나만 존재하기 때문이다.

즉 모든 B-Tree 인덱스에 대하여 하나의 어댑티브 해시 인덱스에서 관리해야 하므로,

특정 키 값이 어느 인덱스에 속한 것인지 구분해야 하기 때문이다.

 

어댑티브 해시 인덱스가 가지는 '데이터 페이지 주소'는 버퍼 풀에 로딩된 페이지의 주소를 의미한다.

어댑티브 해시 인덱스는 버퍼 풀에 올려진 데이터 페이지에 대해서만 관리되므로,

버퍼 풀에서 해당 데이터 페이지가 없어지면 어댑티브 해시 인덱스에서도 제거된다.

 

 

 

✔️ 파티셔닝

8.0 이전 버전에서는 어댑티브 해시 인덱스는 하나로만 관리되어 경합(Contention)이 심했다.

8.0 부터는 내부 잠금(세마포어) 경합을 줄이기 위해 파티션 기능을 제공한다.

innodb_adaptive_has_index_parts 를 통해 변경 가능하며, 기본 개수는 8개이다.

 

 

 

✔️ 상황에 따른 효율

어댑티브 해시 인덱스가 성능 향상에 도움이 되지 않는 경우는 다음과 같다.

  • 디스크 읽기가 많은 경우
  • 조인이나 LIKE 검색이 많은 경우
  • 큰 데이터를 가진 테이블을 넓게 읽는 경우

 

다음과 같은 상황에는 도움이 된다.

  • 디스크의 데이터가 버퍼 풀 크기와 비슷한 경우 (디스크 읽기가 많지 않은 경우)
  • 동등 비교, IN 연산이 많이 사용되는 경우
  • 쿼리가 데이터 중에서 일부 데이터에만 집중되는 경우

 

어댑티브 해시 인덱스는 데이터 페이지를 메모리(버퍼 풀) 내에서 접근하는 것을 더 빠르게 만드는 기능이다.

디스크에서 데이터를 읽어오는 경우가 빈번한 경우 아무런 도움이 되지 못 하므로,

불필요한 경우 사용하지 않는 것이 좋다.

 

 

어댑티브 해시 인덱스가 현재 유용한지 파악하는 법을 살펴보자.

SHOW ENGINE INNODB STATUS\G

 

위 결과는 초당 172.65(31.26 + 141.39)번의 검색이 실행됐는데,

그중 31.26번은 어댑티브 해시 인덱스 사용했고,

141.39번은 그렇지 못했다는 것을 보여준다.

 

searches가 의미하는 것은 쿼리의 실행 횟수가 아닌,

쿼리를 처리하기 위해 내부적으로 키의 검색이 몇 번 실행됐는지를 의미한다.

 

어댑티브 해시 인덱스의 효율은 다음을 종합하여 판단해야 한다.

  • 해시 인덱스 히트율(hash searches / non-hash searches)
  • 어댑티브 해시 인덱스가 사용중인 메모리 공간
  • 서버의 CPU 사용량

 

어댑티브 해시 인덱스가 사용중인 메모리 공간의 크기는 다음과 같이 확인할 수 있다.

SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED
FROM performance_schema.memory_summary_global_by_event_name
WHERE EVENT_NAME='memory/innodb/adaptive hash index';

 

 

 

 

 

참고