MySQL InnoDB 버퍼 풀은 쿼리의 성능과 밀접하게 연결돼 있다.
버퍼 풀은 메모리 상에 적재되고, 애플리케이션의 DML을 통해 조작된다.
조작하려는 데이터가 이미 버퍼풀에 존재한다면, 메모리 I/O 만 일어나므로 애플리케이션은 빠른 응답을 받을 수 있다.
하지만 조작하려는 데이터가 버퍼풀에 존재하지 않는다면, 디스크로부터 데이터 페이지를 버퍼풀에 로드하는 과정이 선행되고, 이 과정은 디스크 I/O가 발생하므로 상대적으로 느리다.
@RestController
@RequiredArgsConstructor
public class ExampleController {
private final ExampleEntityRepository repository;
@GetMapping("/test-buffer-hit")
public String testBufferHit() {
// 첫 번째 요청 (버퍼 풀에 없는 경우)
long start1 = System.currentTimeMillis();
Optional<ExampleEntity> entity1 = repository.findById(1L);
long end1 = System.currentTimeMillis();
// 두 번째 요청 (버퍼 풀에 있는 경우)
long start2 = System.currentTimeMillis();
Optional<ExampleEntity> entity2 = repository.findById(1L);
long end2 = System.currentTimeMillis();
return String.format(
"First Query Time: %d ms, Second Query Time: %d ms",
(end1 - start1), (end2 - start2)
);
}
}
간단히 속도 측정 테스트를 해보았다. 과정은 다음과 같다.
2에서 서버를 Shutdown 하는 이유는 데이터 삽입 시 버퍼풀에 페이지가 존재하기 때문이다.
테스트 결과
첫 번째 요청(버퍼풀에 데이터 X)은 디스크 -> 버퍼풀
로 데이터를 읽어오는 과정이 포함되어,
두 번째 요청(버퍼풀에 데이터 O)에 비해 상당히 느리게 처리된 것을 확인할 수 있다.
워밍업은 쿼리에 사용되는 데이터가 버퍼 풀에 적재돼 있는 상태를 의미한다.
MySQL 5.5 버전 이하에서는 점검을 위해 MySQL 서버를 재시작해야하는 경우, 서비스를 오픈하기 전에 강제 워밍업을 위해 주요 테이블과 인덱스에 대해 풀 스캔을 한 번씩 실행하고 서비스를 오픈했다고 한다.
하지만 MySQL 5.6 이후 버전에서는 버퍼 풀 덤프 및 적재 기능이 도입됐다.
서버 재시작시, 버퍼 풀의 백업과 복구를 할 수 있는 기능으로
innodb_buffer_pool_dump_at_shutdown
과 innodb_buffer_pool_load_at_startup
설정을 MySQL 설정 파일에 넣어두면 된다고 한다.