知识卡片
冷热数据混在同一物理页,会让整页被误判为"热"
内容
[[工作集概念缓存单位放大让聚簇索引选择影响缓存效率]]说明了缓存是按
“页”这个物理单位工作的,这里补上一个直接后果:如果活跃(热)和不活跃
(冷)的数据混在同一张表、恰好又落进了同一个物理页里,InnoDB是按页
整体判断和缓存”热度”的,只要这一页里有任何一行被访问,整页都会被当作
热数据留在缓冲池里。举例来说,一个页能存100个用户的数据,其中只有
10%是活跃用户,但因为这10%的访问,其余90%本不该被缓存的冷数据也会
跟着一起占用缓冲池空间——缓存空间的浪费不是发生在”数据本身该不该缓存”
这个判断上,而是发生在”缓存的最小粒度是页、而不是行”这个物理约束上。
解决办法不是让InnoDB变聪明去识别页内的行级热度(这在B-Tree存储引擎的
物理布局下做不到),而是从schema设计上主动把冷热数据分离到不同的表,
让它们各自聚集进各自的物理页,比如把users表拆成active_users和
inactive_users两张表;如果数据按时间自然变热变冷(比如博客系统里
最近一周的文章和评论是访问热点),也可以按时间维度做数据分区,让最新
数据集中落在少数几页里,方便整体常驻内存。这是”缓存单位放大效应”给
schema设计的一条具体启发:表结构的物理布局本身就是缓存效率的一个
可调设计维度,不是只有加内存这一条路。
参考来源
- 位置:《高性能MySQL:第3版》第11章"可扩展的MySQL"11.2.7节"向内
扩展"(源文件:_epub-src/OEBPS/Text/part0018.xhtml)
- 结论依据:原文明确"如果用的是InnoDB,每次缓存一页,而一页能存储
100个用户,但只有10%是活跃的,那么这时候InnoDB可能认为所有的页
都是'热'的——因此每个'热'页的90%将被浪费掉。将其拆成两个表可以
明显改善内存利用率",直接说明冷热数据混页导致缓存浪费的机制及拆表
这一具体解决办法。
- 原始内容:如果用的是InnoDB,每次缓存一页,而一页能存储100个用户,
但只有10%是活跃的,那么这时候InnoDB可能认为所有的页都是"热"的——
因此每个"热"页的90%将被浪费掉。