본문 바로가기
DB

mysql 아키텍쳐[2] - 버퍼풀

by 코딩공장공장장 2025. 2. 7.

버퍼풀 자료구조


버퍼풀은 여러개의 데이터 페이지로 이루어져 있다.

버퍼풀은 메모리 공간에 존재하기에 무한정 많은 데이터를 담고 있을 수 없다.

사용하지 않는 데이터는 제거되야한다.

버퍼풀에서 사용되는 자료구조를 살펴보자.

 

LRU(Least Recently Used) 리스트 : 가장 오래동안 사용되지 않은 데이터 페이지 제거

  • New 서브리스트
    - MRU(Most Recently Used) 알고리즘을 통해 가장 많이 읽힌 데이터들이 존재하는 공간
    - 버퍼풀의 데이터를 읽어들이면 해당 데이터는 리스트의 머리부분으로 이동한다.

  • Old 서브리스트 
    - LRU 알고리즘이 사용되는 공간으로 오랫동안 읽히지 않는 데이터 관리
    - 오랫동안 사용되지 않은 데이터는 나이가 증가하고 꼬리 부분으로 이동된다.

데이터를 디스크에서 처음 버퍼풀로 가져오면 old 리스트에 머리에 위치한다.

이후 사용자에 의해 읽혀지면 new 서브리스트로 이동하고 자주 읽힐수록 머리부분으로 이동하게 된다.

데이터가 읽히지 않으면 꼬리부분으로 점차 이동되고  old 서브리스트의 영역이 37%를 넘어가게되면 꼬리부분 데이터 페이지를 제거하는 작업을 수행한다.

(* LRU 리스트는 효율적인 메모리 관리를 위해 불필요한 클린 데이터 페이지를 삭제하기 위한 자료구조이다.)

 

플러시 리스트

플러시 리스트는 변경사항이 반영된 더티 페이지를 디스크에 반영하기 위한 리스트이다.

체크포인트 이벤트 발생 이후 디스크에 기록이 되면 더티 페이지는 제거 된다.

(* 플러시 리스트는 더티페이지의 디스크 반영 목적을 위한 자료구조이다.)

 

버퍼풀 플러시


플러시는 버퍼풀이 비워지는 작업을 의미한다.

LRU 리스트의 버퍼풀의 비워지는 작업은 오랫동안 사용되지 않은 클린 데이터 페이지가 삭제되는 것이고,

플러시 리스트의 버퍼풀이 비워지는 작업은 디스크에 더티페이지가 반영되는 것이다.

 

플러시 기준이 어떻게되는지 살펴보자.

대상 옵션 설명
LRU 리스트 innodb_lru_scan_depth - LRU 리스트를 스캔할 때, 한번에 몇개의 데이터 페이지를 검사할지 결정
- 값이 너무 크면 한번에 많은 페이지를 검사하여 불필요한 페이지를 삭제하는데 효율적일 수 있으나 CPU 부하가 크고, 값이 너무 작으면 불필요한 페이지 삭제 처리 속도가 늦어질 수 있다. (잦은 작업을 유발할 수 있음)
LRU 리스트,
플러시 리스트
innodb_page_cleaners - LRU 리스트와 플러시 리스트를 관리하는 쓰레드 개수
- 디폴트값은 4
- CPU 코어가 많다면 코어 수에 맞춰 높은 동시 처리 가능
   -> 잦은 작업이 아닌 한번의 작업을 일괄적으로 빠르게 처리 가능
플러시 리스트 innodb_max_dirty_pages_pct - 더티 페이지 비율이 일정 수준(%) 이상이면 적극적으로 플러시
- 기본값 90%

 

 

체인지 버퍼


체인지 버퍼는 버퍼풀에 세컨더리 인덱스 페이지가 존재하지 않을 때, 버퍼를 통해 일괄 변경할 수 있도록 하기 위해 존재한다.

인덱스 페이지가 버퍼풀에 존재하면 바로 변경을 하지만 존재하지 않는다면 체인지 버퍼에 기록해두고 디스크에서 인덱스 페이지를 읽어올 때 병합 작업을 하여 버퍼풀에 적재한다.

이 작업을 체인지 버퍼 머지(백그라운드) 스레드가 진행한다.

디스크에 쓰는 작업은 이 과정과 별개로 플러시 리스트를 통해 플러시가 발생하면 데이터가 쓰여지며 인덱스도 함께 수정된다.

 

체인지 버퍼는 bulk insert와 같은 대량의 insert 작업 발생시에는 효과가 크지만 읽기 작업이 많은 경우 메모리에 용량만 차지하기에 적재할 수 있는 데이터 페이지의 크기를 감소시켜 읽기 작업의 성능 저하를 유발할 수 있다.

버퍼의 최대 크기는 default 25%이지만 최대 50%까지 설정 가능하다.

db의 성능을 고려하여 설정하는 것이 바람직해보인다.

Mysql 기반 몇몇 DB에서는 체인지 버퍼를 미지원한다. (Aurora Mysql)

 

어댑티브 해시 인덱스


어댑티브 해시 인덱스는 B-tree 구조의 탐색 보다 더 빠른 성능을 낼 수 있게 지원되는 인덱스이다.

데이터의 물리적인 구조는 pk 기반 B-tree로 이루어져있기에 세컨더리 인덱스 대신 성능 향상을 해야할 목적으로 사용된다.

(세컨더리 인덱스나 해시 인덱스 모두 인덱스의 pk 값을 저장하기에 인덱스 탐색 이후 pk 기반 B-tree 탐색 진행함)

 

B-tree인덱스의 시간 복잡도는 O(logN)이다. 해시 인덱스는 O(1)이다. 해시 함수의 결과로 pk 값을 받기에 노드를 탐색해 나가는 것이 아닌 함수 실행 결과로 pk 값이 반환된다. 

 

해시 인덱스는 동치 비교에 최적화 되어있고 그외 부분일치나 패턴 일치에서는 B-tree보다 성능이 저하되는 경우도 많다.
따라서 사용 가능한 경우가 제한적이기에 해시 인덱스가 많다고 해서 효율적인 것이 아니다. 

해시 인덱스는 오히려 성능 저하를 유발할 수 있다. 해시 인덱스 또한 버퍼풀에 메모리를 차지하기에 해시 인덱스가 많아지면 버퍼풀에 저장할 데이터 페이지의 갯수가 작아질 수 있어 많은 디스크 IO를 유발할 수 있다. 

 

해시 인덱스 기능을 활성화면 모든 인덱스 검색에서 해시 인덱스에 존재하는지 여부를 검사하기에 오버헤드를 유발할 수 있다.

사용 가능한 검색 조건이 많지 않기에 활성화시 더욱 성능 저하를 유발할 수 도 있다.

 

특정 데이터에 집중되어 동등비교를 하는 읽기 작업이 많다면 해시 인덱스를 활성화하는 것이 좋고

여러 테이블에서 읽기 작업을 하거나 읽기 작업 자체가 많지 않다면 해시 인덱스를 비활성화 하는 것이 좋다.

 

 

반응형