知识卡片

临时表算法视图:无法下推条件,也没有索引

普通读书笔记卡

内容

“视图不能提升性能,只是查询的语法糖”是一个常见误解——MySQL视图有两种 不同的底层实现算法,性能特征完全不同,笼统地说”视图快”或”视图慢”都不 准确。用合并算法(MERGE)实现的视图,本质上是把视图定义和外层查询 拼接、重写成一条等价的普通查询交给优化器处理,外层的WHERE条件能像 正常查询一样被下推、也能用上底层表的索引。但当视图定义本身比较复杂 (比如包含GROUP BY、聚合、DISTINCT等),MySQL会退化成用临时表算法 (TEMPTABLE)实现:先把视图定义本身当作一条独立查询完整执行一遍, 把结果物化成一张临时表,再让外层查询在这张临时表上继续执行。这种 “先执行、再关联”的方式带来两个实打实的代价:外层查询里能过滤掉大部分 数据的WHERE条件(比如一个日期范围)根本无法下推进视图定义的查询里, 所以生成临时表这一步会不打折扣地处理视图涉及的全部数据,即使外层最终 只要其中一小段;而且这张临时表本身不建索引,如果外层查询要拿它去跟 别的表关联,只能靠全表扫描或者临时表恰好排在关联顺序最前面才能借上 别的表的索引,一旦是两个视图互相关联,就完全没有索引可用。这解释了 为什么一条”看起来只是查一张简单视图”的查询,EXPLAIN出来却可能有几 百行、执行计划复杂得难以预料——视图背后到底走的是合并算法还是临时表 算法,直接决定了它是”几乎零代价的语法糖”还是”每次都要先物化一遍全量 数据的隐藏开销”,不能凭直觉判断,必须结合视图定义本身和EXPLAIN结果 具体核实。

参考来源

- 位置:《高性能MySQL:第3版》第7章"MySQL高级特性"7.2.2节"视图对性能 的影响"(源文件:_epub-src/OEBPS/Text/part0014.xhtml) - 结论依据:原文明确"使用临时表算法实现的视图,在某些时候性能会很 糟糕……外层查询的WHERE条件无法'下推'到构建视图的临时表的查询中, 临时表也无法建立索引……如果是对两个视图做关联的话,优化器就没有 任何索引可以使用了",直接说明临时表算法视图WHERE无法下推、无索引 的具体机制及其性能后果。 - 原始内容:使用临时表算法实现的视图,在某些时候性能会很糟糕……外层 查询的WHERE条件无法"下推"到构建视图的临时表的查询中,临时表也无法 建立索引。