The query cache stores result sets keyed by the exact query text and invalidates every entry for a table whenever that table is written. On anything with writes, the invalidation costs more than the cache saves.
SHOW VARIABLES LIKE 'query_cache%';
-- query_cache_type OFF ← the correct value
-- query_cache_size 0
SHOW STATUS LIKE 'Qcache_lowmem_prunes'; -- if this climbs, it is thrashing
It also takes a global mutex to invalidate, which serialises writes across every connection — so it gets slower as concurrency rises, which is the opposite of what a cache should do. It has been off by default since 5.6 and is removed entirely in 8.0. Anything still enabling it is following advice written for MySQL 5.1.