알쓸코지
article thumbnail
InnoDB 스토리지 엔진은 특정 테이블의 연속된 데이터 페이지가 읽히면 백그라운드 스레드에 의해 리드 어헤드(Read ahead) 작업이 자동으로 시작된다.
- Real MySQL 8.0의 9.2.1

책에서 리드 어헤드에 대해서 간단히 언급하고 지나갔는데, 더 자세히 알아보고 싶어서 정리하게 되었다. 


풀 테이블 스캔

`풀 테이블 스캔(Full Table Scan)`인덱스를 사용하지 않고, 테이블의 데이터를 처음부터 끝까지 읽어서 요청된 작업을 처리하는 작업으로, 테이블의 레코드 건수가 너무 작거나 적절한 인덱스가 없을 때 이 방식을 사용한다.

https://hoon93.tistory.com/53

풀 테이블 스캔 방식의 문제점은 테이블의 모든 행을 순차적으로 읽어오기 때문에 상당히 많은 디스크 I/O가 필요하다는 것인데, 대부분의 DBMS는 성능 최적화를 위해 한 번의 디스크 I/O에 인접한 여러 개의 블록이나 페이지를 읽어온다. (MultiBlock I/O)

 

>MySQL의 경우, MyISAM, InnoDB 중 어떤 스토리지 엔진을 사용하느냐에 따라 적용 여부가 달라진다.

  • `MyISAM`은 `MultiBlock I/O`가 적용되지 않는다. 즉, 풀 테이블 스캔을 실행하면 디스크로부터 페이지를 하나씩 읽어 온다.
  • `InnoDB`는 `MultiBlock I/O`가 적용된다. 특정 테이블의 연속된 데이터 페이지가 읽히면 백그라운드 스레드에 의해 `리드 어헤드` 작업이 자동으로 시작된다. 

 

리드 어헤드(Read ahead)

어떤 영역의 데이터가 앞으로 필요해지리라는 것을 예측해서 요청이 오기 전에 미리 디스크에서 읽어 InnoDB의 버퍼 풀에 가져다 두는 것을 의미한다.

  • 풀 테이블 스캔이 실행되면 포그라운드에 의해 `innodb_read_ahead_threshold` 변수값만큼 연속된 데이터 페이지 읽고 나서 읽기 작업을 백그라운드 스레드에게 넘긴다.
  • 백그라운드 스레드는 대량(한 번에 최대 64페이지)으로 페이지들을 읽어서 버퍼 풀에 적재한다.
  • 포그라운드 스레드는 미리 버퍼 풀에 준비된 데이터를 가져다 사용하기만 하면 되므로 쿼리 처리 속도가 향상된다.

여기까지가 책에서 설명한 리드 어헤드의 동작 방식인데, 조금 더 자세히 알아보고 싶어서 공식 문서를 찾아 보았다.

 

공식 문서 내용 정리

https://dev.mysql.com/doc/refman/8.0/en/innodb-performance-read_ahead.html<

 

MySQL :: MySQL 8.0 Reference Manual :: 15.8.3.4 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead)

15.8.3.4 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead) A read-ahead request is an I/O request to prefetch multiple pages in the buffer pool asynchronously, in anticipation of impending need for these pages. The requests bring in all the pages in

dev.mysql.com

💡
A read-ahead request is an I/O request to prefetch multiple pages in the buffer pool asynchronously, in anticipation of impending need for these pages. The requests bring in all the pages in one extent.

`리드 어헤드(read-ahead) 요청`은 버퍼 풀에서 해당 페이지에 대한 수요가 임박할 것을 예측하여 비동기적으로 프리페치하는(미리 가져오는) I/O 요청이다. 이 요청은 하나의 `익스텐트(extent)`에 해당하는 모든 페이지를 가져온다.
  • `익스텐트(extent)`: 페이지들을 그룹화하는 단위
    • 기본 페이지 크기가 16KB인 경우, 익스텐트에는 64개의 페이지가 포함되어 있다.

https://cl8d.tistory.com/103

  • 날짜 데이터를 나누어서 비유해 보자면,
    • `Segment`: 년 - ex) `2021년 데이터` ~ `2024년 데이터`
    • `Extent`: 월 - ex) `2023년 1월 데이터` ~ `2023년 12월 데이터`
    • `Page`: 일 - ex) `2024년 1월 1일` ~ `2024년 1월 31일`
    • `Row`: 특정 날짜에 해당하는 개별 레코드 - ex) `2024년 1월 1일 A`, `2024년 1월 1일 B`, `2024년 1월 1일 C`, ...

 

프리패칭 방식은 `Linear read-ahead`, `Random read-ahead` 두 가지로 구분된다.

Linear read-ahead(선형 리드 어헤드)

https://goodbyeanma.tistory.com/42

  • MySQL에 설정된 값(`innodb_read_ahead_threshold`)만큼 디스크에서 `익스텐트(extent)` 내부에 저장된 페이지를 순차적으로 읽게 된다면 다음 익스텐트를 프리패칭한다.
  • `innodb_read_ahead_threshold` 값은 0부터 64까지 가질 수 있으며, 값이 낮을수록 리드 어헤드가 더 자주 발생한다.

Random read-ahead(랜덤 리드 어헤드)

랜덤 리드 어헤드의 동작 방식이 너무 궁금한데 검색해 봐도 자료를 못 찾겠어서 대충 이런 흐름이 아닐까.. 하고 만들어 본 자료입니다😭 랜덤 리드 어헤드 고수님이 계신다면 댓글 부탁드립니다..🙇🏻‍♀️
  • 선형 리드 어헤드와 달리 랜덤한 순서로 액세스 될 가능성이 있는 페이지를 가져오는 데 중점을 둔다.
  • 버퍼 풀에서 동일한 익스텐트의 13개의 연속된 페이지를 발견하면 익스텐트의 남은 페이지를 프리패칭한다. 
  • 이 기능을 활성화하려면 `innodb_buffer_poll_read_ahead` 변수를 `ON`으로 설정!

통계 정보

SHOW ENGINE INNODB STATUS

위의 명령어는 리드 어헤드 알고리즘 성능을 평가하는데 도움이 되는 통계 정보를 제공하며, 아래와 같은 전역 상태 변수를 포함한다.

  • `Innodb_buffer_pool_read_ahead`
    • 백그라운드 스레드에 의해 InnoDB 버퍼 풀로 미리 읽어 들인 총 페이지 수
  • `Innodb_buffer_pool_read_ahead_evicted`
    • 백그라운드 스레드에 의해 미리 읽은 페이지 중에서 실제로 쿼리에서 액세스 하지 않고 나중에 제거된 페이지 수
    • 미리 읽은 페이지가 얼마나 유용한지 평가하는 지표로 사용됨
  • `Innodb_buffer_pool_read_ahead_rnd`
    • InnoDB에 의해 발생된 `랜덤` 리드 어헤드 수

 

Ref

Real MySQL 8.0

https://hoon93.tistory.com/53

https://engineerinsight.tistory.com/227

https://velog.io/@fishphobiagg/%EC%BF%BC%EB%A6%AC-%ED%8A%9C%EB%8B%9D%EC%9D%98-IO-%EB%B3%91%EB%AA%A9-%EA%B0%9C%EC%84%A0-%EC%9B%90%EB%A6%AC-With-MySQL-JPA

https://dev.mysql.com/doc/refman/8.0/en/innodb-performance-read_ahead.html

https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_extent

 

 

 

 

'Backend > Database' 카테고리의 다른 글

[MySQL] 실행 계획 - partitions 칼럼  (0) 2024.02.15
[MySQL] 히스토그램  (0) 2024.02.07
[MySQL] B-Tree 알고리즘  (0) 2024.01.18
[MySQL] 암호화 알고리즘  (0) 2024.01.11
[MySQL] 격리성 수준에 따른 MVCC  (0) 2024.01.04
profile

알쓸코지

@chocoji

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!