为何含UNION ALL的MySQL视图查询速度远慢于直接执行同逻辑SQL?
为何直接执行UNION ALL查询比查询对应视图更快?
直接执行的查询语句:
SELECT col1, col2, col3, col4, col5 FROM table_1 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_2 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_3;
基于上述语句创建视图的语句:
CREATE VIEW test_table_x AS SELECT col1, col2, col3, col4, col5 FROM table_1 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_2 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_3;
table_1、table_2、table_3各有5000条记录,直接执行上述SQL耗时约0.0050秒,而执行 SELECT * FROM test_table_x; 耗时约0.107秒。
补充说明
已添加MySQL的EXPLAIN结果:
直接SQL的EXPLAIN语句及结果
EXPLAIN SELECT col1, col2, col3, col4, col5 FROM table_1 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_2 UNION ALL SELECT col1, col2, col3, col4, col5 FROM table_3;
结果显示:查询计划包含三个全表扫描步骤,依次访问table_1、table_2、table_3,每个表预估扫描行数为5000,Extra列无额外操作标记。
视图查询的EXPLAIN语句及结果
EXPLAIN SELECT col1, col2, col3, col4, col5 FROM test_table_x;
结果显示:查询计划将视图定义展开后,同样对三个表执行全表扫描,但执行细节与直接查询存在差异(比如可能存在隐式临时表操作或执行顺序的细微调整)。
原因分析
MySQL中的普通视图属于逻辑视图,仅存储查询定义,查询视图时会先将视图语句展开为原始查询再执行。理论上两者性能应一致,但出现差异通常有以下几点原因:
- 缓存影响:如果使用的是MySQL 5.x版本(存在查询缓存),直接查询的语句可能已命中缓存,而查询视图的语句文本不同,无法复用缓存,需重新执行物理查询。即使是8.0版本,缓冲池中的数据页缓存也可能存在差异——直接查询后数据页已加载到内存,视图查询时可能需要重新读取磁盘。
- 执行计划的隐性差异:虽然表面都是全表扫描,但视图展开后的查询可能触发额外的隐式操作,比如部分MySQL版本在处理视图时会不必要地创建临时表(即使UNION ALL不需要去重),带来额外的IO和内存开销。可以对比两个EXPLAIN的Extra列,若视图查询出现
Using temporary,则这是核心原因。 - 元数据加载开销:查询视图时,MySQL需要先从系统表中读取视图的元数据并解析展开,这一步的微小开销在小数据量场景下占比被放大,导致耗时差异更明显。
- 统计信息偏差:若表的统计信息过时,MySQL生成视图执行计划时可能基于旧数据选择次优路径,而直接查询时能基于较新的统计信息生成更高效的计划。
验证建议
- 若使用MySQL 5.x,关闭查询缓存(设置
query_cache_type=0)后重新测试,排除缓存干扰; - 仔细对比两个EXPLAIN结果的
Extra、Rows等字段,确认执行计划的细节差异; - 执行
ANALYZE TABLE table_1, table_2, table_3;更新表统计信息后,再次对比两者耗时; - 尝试用
SELECT col1, col2, col3, col4, col5 FROM test_table_x;(指定字段而非*)查询视图,看耗时是否接近直接查询。
内容的提问来源于stack exchange,提问作者James Arnold
相关产品推荐
相关产品推荐

