知识卡片

打开并锁住所有底层表,是分区表的固定开销

普通读书笔记卡

内容

[[分区裁剪只认分区列本身遇到表达式就失效]]描述的裁剪机制,只影响 “最终扫描哪些分区数据”这一层;但在分区裁剪生效之前,MySQL访问一张 分区表时,需要先打开并锁住这张表底下的全部物理子表——这个操作发生在 分区过滤判断之前,因此完全不受分区裁剪结果影响,也和具体用的是哪种 分区类型无关,是所有对分区表的查询都要承担的固定代价。这个开销对 那些本身执行很快的操作影响格外明显:比如一次根据主键查找单行这种 原本几乎瞬时完成的查询,在分区表上会因为”先要打开锁住所有子表”这一步 而多出一段和数据量、查询复杂度都无关的固定延迟。缓解思路不是让这一步 变快,而是从两个方向减少它被触发的次数:一是把大量小操作合并成批量 操作(用批量插入、LOAD DATA INFILE、一次删除多行等方式,让”打开锁住 所有子表”这个固定成本被更多行数据摊薄);二是限制分区总数(不同分区 类型对分区数的敏感度不同,范围分区尤其明显,因为”判断一行该落进哪个 分区”本身就是对分区定义列表做线性搜索,分区越多这一步越慢,经验上把 分区数控制在100个左右比较安全)。这说明评估分区表是否值得引入时,不能 只看”分区裁剪能省掉多少扫描量”这一个维度,还要把这类与裁剪无关的固定 开销一起算进总账。

参考来源

- 位置:《高性能MySQL:第3版》第7章"MySQL高级特性"7.1.4节"什么情况下 会出问题"(源文件:_epub-src/OEBPS/Text/part0014.xhtml) - 结论依据:原文明确"当查询访问分区表的时候,MySQL需要打开并锁住所有 的底层表,这是分区表的另一个开销。这个操作在分区过滤之前发生,所以 无法通过分区过滤降低此开销,并且该开销也和分区类型无关,会影响所有 的查询。这一点对一些本身操作非常快的查询,比如根据主键查找单行,会 带来明显的额外开销",直接说明该开销的发生时机、与分区裁剪无关的 性质及缓解办法。 - 原始内容:当查询访问分区表的时候,MySQL需要打开并锁住所有的底层 表,这是分区表的另一个开销……可以用批量操作的方式来降低单个操作的 此类开销。