Zettelkasten

ReadIOPS는 논리 읽기 요청이 아니라 디스크 물리 읽기를 센다

·수정 2

요약

  • CloudWatch ReadIOPS는 데이터 볼륨(디스크)에 완료된 물리 읽기 연산/초다 (공식 문구는 "disk read I/O operations"; gp3/io 스토리지면 그 디스크가 EBS). SQL이 요청한 논리 읽기가 아니라, 버퍼 풀에서 못 찾아 디스크까지 내려간 읽기만 잡힌다.
  • 따라서 ReadIOPS는 버퍼 풀 read miss의 대리지표다. 단 InnoDB와 디스크 사이에 OS 페이지 캐시가 끼면 miss여도 ReadIOPS가 안 생길 수 있는데, innodb_flush_method=O_DIRECT면 OS 캐시를 우회해 miss가 곧장 ReadIOPS로 드러난다.
  • 논리 읽기 요청 수는 Innodb_buffer_pool_read_requests로 따로 집계되며 hit를 포함한다 — 두 지표를 혼동하면 안 된다.

본문

"ReadIOPS"를 SQL 쿼리가 읽은 양으로 오해하기 쉽지만, 디스크 기준이다. AWS CloudWatch 메트릭 레퍼런스 원문: "ReadIOPS — The average number of disk read I/O operations per second." — 즉 데이터 볼륨에 완료된 물리 읽기 연산 수다. 문서 문구는 "disk"까지이며, 이 디스크가 EBS인지 로컬 NVMe인지는 인스턴스 구성에 따른다(gp3/io면 EBS 데이터 볼륨). 로컬 스토어·로그 볼륨은 ReadIOPSLocalStorage·ReadIOPSLogVolume로 메트릭이 분리돼 있다.

hit는 ReadIOPS에 안 잡힌다. 쿼리가 페이지를 읽을 때 버퍼 풀에 있으면(hit) 디스크로 안 가므로 ReadIOPS가 생기지 않고, 없으면(miss) 디스크에서 물리적으로 읽어 ReadIOPS로 카운트된다. 그래서 ReadIOPS가 낮다 = 디스크까지 내려간 읽기가 적다 = 버퍼 풀이 읽기를 거의 다 흡수 중이라는 인과가 성립한다. 데이터셋이 버퍼 풀보다 훨씬 커도 ReadIOPS가 낮으면 핫셋이 작다는 증거가 된다.

중간 캐시 레이어 주의. 이론상 InnoDB와 디스크 사이에 OS 페이지 캐시가 끼면, 버퍼 풀 miss여도 OS 캐시가 받아서 물리 읽기가 안 생기고 ReadIOPS가 인위적으로 낮게 보일 수 있다. 이 레이어 유무는 innodb_flush_method로 갈린다:

  • O_DIRECT (RDS MySQL의 흔한 기본값): InnoDB 데이터 파일 I/O가 OS 캐시를 우회 → 버퍼 풀 miss가 곧 물리 읽기로 나타난다(read-ahead 등으로 페이지당 정확히 1:1은 아니나 대체로 대응). ReadIOPS가 버퍼 풀 미스율의 깨끗한 대리지표가 된다.
  • 버퍼드 I/O면 OS 캐시가 일부 흡수 → ReadIOPS가 미스율을 과소평가할 수 있음.

→ ReadIOPS로 캐시 효율을 논할 땐 innodb_flush_method를 먼저 확인해야 정확하다.

논리 읽기와 구분. 논리 읽기 요청(hit 포함)은 Innodb_buffer_pool_read_requests로 따로 집계된다. 버퍼 풀 히트율 = 1 − Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests. 여기서 Innodb_buffer_pool_reads(디스크에서 채운 페이지)가 ReadIOPS와 대응하는 쪽이다. 즉 ReadIOPS와 히트율은 같은 사실(물리 읽기가 적다)의 두 관점이고, ReadIOPS는 디스크/IO 부하를 절대값으로, 히트율은 비율로 본다.

지표 기준 hit 포함?
ReadIOPS (CloudWatch) 디스크(데이터 볼륨) 물리 읽기
Innodb_buffer_pool_read_requests 논리 읽기 요청

실측 교차검증 (New Relic). 같은 앱이 MySQL SELECT를 ~648/s 날리는데 물리 ReadIOPS는 master 48/s vs read replica 686/s로 13배 차이가 났다. 쿼리 스트림은 하나인데 노드별 ReadIOPS가 갈린다 = ReadIOPS가 쿼리 수가 아니라 각 노드의 버퍼 풀 상태(물리 미스)를 따라간다는 직접 증거다. (단 APM datastore 메트릭의 instanceName은 DB 엔드포인트가 아니라 앱 노드라, master/replica별 논리:물리 1:1 대응은 on-host MySQL 메트릭이 있어야 확정 — ⚠️ 미확인.)

관련 노트

참고