Performanceintermediate
Cache Hit Ratio
Reading cache statistics correctly per engine, and knowing when a falling ratio matters and when it does not.
Cache hit ratio is the fraction of reads served from memory. It is the clearest early indicator that the working set has outgrown the cache — and it is frequently misread.
Per engine
-- PostgreSQL: buffer cache hit ratio.
SELECT sum(heap_blks_hit) * 100.0 / nullif(sum(heap_blks_hit + heap_blks_read), 0) AS hit_pct
FROM pg_statio_user_tables;
-- Per table, to find the one that is missing.
SELECT relname,
round(100.0 * heap_blks_hit / nullif(heap_blks_hit + heap_blks_read, 0), 1) AS hit_pct,
heap_blks_read
FROM pg_statio_user_tables
WHERE heap_blks_hit + heap_blks_read > 10000
ORDER BY heap_blks_read DESC LIMIT 20;-- MySQL / InnoDB.
SELECT
(1 - reads.value / requests.value) * 100 AS hit_pct
FROM performance_schema.global_status reads,
performance_schema.global_status requests
WHERE reads.variable_name = 'Innodb_buffer_pool_reads'
AND requests.variable_name = 'Innodb_buffer_pool_read_requests';INFO stats -- Redis: keyspace_hits and keyspace_misses// MongoDB: WiredTiger cache pressure.
db.serverStatus().wiredTiger.cache;Reading it correctly
For Redis, the ratio means something different again: it measures whether the application is asking for keys that exist, not whether the data is in memory — everything in Redis is in memory. A falling Redis hit ratio means keys are being evicted, expiring, or were never written. See Redis Monitoring.
What a falling ratio means
- Data growth. The working set genuinely no longer fits.
- A new query pattern. A report scanning a large table evicts the hot pages every time it runs.
- A cache-unfriendly access pattern. Random access over a large key space, or a large sequential scan.
- A restart. A cold cache after a restart looks like a crisis and resolves itself as the cache warms. Distinguish the two before acting.
What to do
- Confirm the workload changed before assuming the data did. A single new query can explain the whole shift.
- Reduce the working set — archive, partition, drop unused indexes competing for cache.
- Isolate scan-heavy work onto a replica so it does not evict the transactional working set.
- Then consider more memory.