DBAtlas · 데이터베이스 운영 아틀라스

낮은 캐시 적중률(buffer/cache hit)

캐시 적중률이 낮아 데이터가 계속 디스크(또는 원본)에서 읽힌다. 문제가 DB buffer/shared cache에 있는지 Redis/애플리케이션 캐시에 있는지 파악한 뒤 측정하고 수정한다.

어떤 캐시의 적중률이 낮은가?

적중률을 측정하고 문제를 분리한다: 데이터베이스 buffer/shared cache가 낮은가(물리 읽기가 많음), 아니면 Redis/애플리케이션 캐시에서 miss와 eviction이 많은가?

SELECT ROUND((1-(pr.value/(dbg.value+cg.value)))*100,2) AS buffer_hit_pct
FROM v$sysstat pr, v$sysstat dbg, v$sysstat cg
WHERE pr.name='physical reads' AND dbg.name='db block gets' AND cg.name='consistent gets';
  • DB buffer/shared cache 적중률이 낮음
  • Redis/애플리케이션 캐시에서 miss / eviction이 많음

왜 디스크에서 읽는가: 크기인가, 스캔 패턴인가?

낮은 buffer 적중률에는 두 가지 대표 원인이 있다: 자주 접근하는 데이터(working set)가 메모리에 들어가지 않거나(캐시가 너무 작음), 대규모 전체 테이블 스캔이 일회용 블록으로 캐시를 오염시켜 유용한 페이지를 밀어낸다.

SELECT component, current_size/1024/1024 AS mb FROM v$sga_dynamic_components WHERE component LIKE '%buffer cache%';
SELECT sql_id, disk_reads, executions FROM v$sql ORDER BY disk_reads DESC FETCH FIRST 10 ROWS ONLY;
  • working set이 RAM에 들어가지 않음(캐시가 너무 작음)
  • 전체 테이블 스캔이 캐시를 오염시킴

Redis miss의 원인: maxmemory eviction인가, TTL/키 관리인가?

Redis 적중률이 낮다면 메모리가 maxmemory에 도달해 키가 eviction되고 있거나, 키의 TTL 관리/캐싱 패턴이 약하다(콜드 키, 낮은 재사용).

INFO memory
# used_memory, maxmemory, maxmemory_policy, evicted_keys
CONFIG GET maxmemory-policy
INFO keyspace
# Key count and expires (keys with TTL) ratio per db
  • maxmemory 가득 참, 높은 eviction
  • 약한 TTL/키 패턴(낮은 재사용)

근본 원인: working set에 비해 캐시가 너무 작음

자주 접근하는 데이터가 할당된 buffer/cache보다 커서 계속 밀려나고 디스크에서 다시 읽힌다. 적중률은 낮고 물리 읽기는 많다.

근본 원인: 스캔 패턴이 캐시를 오염시킴

대규모 전체 테이블 스캔이 한 번 사용되고 버려지는 블록으로 캐시를 채워 핫 페이지를 밀어낸다. 이로 인해 적중률이 떨어진다.

근본 원인: Redis maxmemory eviction

Redis 메모리가 maxmemory 한도에 도달해 새 키를 위한 공간을 만들려고 오래된 키를 eviction한다(evicted_keys가 계속 증가). 이로 인해 아직 필요한 항목이 사라지고 적중률이 떨어진다.

근본 원인: 약한 TTL / 캐싱 패턴

키에 TTL이 전혀 없어 메모리가 콜드 데이터로 가득 차거나, 캐싱 패턴의 재사용률이 낮아 대부분의 요청이 miss로 끝난다.

DBAtlas에서 열기 →