知识卡片
打开并锁住所有底层表,是分区表的固定开销
内容
[[分区裁剪只认分区列本身遇到表达式就失效]]描述的裁剪机制,只影响
“最终扫描哪些分区数据”这一层;但在分区裁剪生效之前,MySQL访问一张
分区表时,需要先打开并锁住这张表底下的全部物理子表——这个操作发生在
分区过滤判断之前,因此完全不受分区裁剪结果影响,也和具体用的是哪种
分区类型无关,是所有对分区表的查询都要承担的固定代价。这个开销对
那些本身执行很快的操作影响格外明显:比如一次根据主键查找单行这种
原本几乎瞬时完成的查询,在分区表上会因为”先要打开锁住所有子表”这一步
而多出一段和数据量、查询复杂度都无关的固定延迟。缓解思路不是让这一步
变快,而是从两个方向减少它被触发的次数:一是把大量小操作合并成批量
操作(用批量插入、LOAD DATA INFILE、一次删除多行等方式,让”打开锁住
所有子表”这个固定成本被更多行数据摊薄);二是限制分区总数(不同分区
类型对分区数的敏感度不同,范围分区尤其明显,因为”判断一行该落进哪个
分区”本身就是对分区定义列表做线性搜索,分区越多这一步越慢,经验上把
分区数控制在100个左右比较安全)。这说明评估分区表是否值得引入时,不能
只看”分区裁剪能省掉多少扫描量”这一个维度,还要把这类与裁剪无关的固定
开销一起算进总账。
参考来源
- 位置:《高性能MySQL:第3版》第7章"MySQL高级特性"7.1.4节"什么情况下
会出问题"(源文件:_epub-src/OEBPS/Text/part0014.xhtml)
- 结论依据:原文明确"当查询访问分区表的时候,MySQL需要打开并锁住所有
的底层表,这是分区表的另一个开销。这个操作在分区过滤之前发生,所以
无法通过分区过滤降低此开销,并且该开销也和分区类型无关,会影响所有
的查询。这一点对一些本身操作非常快的查询,比如根据主键查找单行,会
带来明显的额外开销",直接说明该开销的发生时机、与分区裁剪无关的
性质及缓解办法。
- 原始内容:当查询访问分区表的时候,MySQL需要打开并锁住所有的底层
表,这是分区表的另一个开销……可以用批量操作的方式来降低单个操作的
此类开销。