SQL性能优化:16次UNION ALL内JOIN同视图,还是子查询后单次JOIN?
性能对比:两种UNION ALL关联视图的方案哪个更高效?
我需要执行16次UNION ALL操作,每个操作都要关联同一个视图view_project。这些UNION ALL的数据来自16个不同的视图view_categoryX,每个view_categoryX会按project_id汇总对应类别的行项目数据(每个类别对应独立表,暂无法重构表结构)。最终需要得到如下格式的数据:
| project | category | total |
|---|---|---|
| 1 | rentals | $10 |
| 1 | equipment | $200 |
| 2 | rentals | $10 |
| 2 | equipment | $300 |
目前有两种实现方案,想知道哪种性能更高效?
方案一:每次关联后执行UNION ALL
每个UNION ALL的SELECT语句中都通过INNER JOIN关联view_project,并添加view_project.is_open = 1的过滤条件,示例代码如下:
select view_project.project_name, view_project.num, view_project.fiscal_year, view_category1.name, view_category1.total from view_category1 inner join view_project on view_project.project_id = view_category1.project_id where view_project.is_open = 1 union all select view_project.project_name, view_project.num, view_project.fiscal_year, view_category2.name, view_category2.total from view_category2 inner join view_project on view_project.project_id = view_category2.project_id where view_project.is_open = 1 ... /* 按此模式重复,共16次UNION ALL */
方案二:先合并类别数据再关联主视图
先将16个view_categoryX通过UNION ALL合并为子查询view_category_total,再通过INNER JOIN与view_project关联,并添加过滤条件,示例代码如下:
select view_project.project_name, view_project.num, view_project.fiscal_year, view_category_total.name, view_category_total.total from view_project inner join ( select category_name, total from view_category1 union ALL select category_name, total from view_category2 ... /* 按此模式重复,共16次UNION ALL */ ) view_category_total On view_project.project_id = view_category_total.project_id where view_project.is_open = 1
性能对比结论
方案二的性能通常更高效,核心原因如下:
- 减少重复计算开销:方案一中
view_project会被关联、过滤16次,若该视图本身包含复杂逻辑(多表关联、聚合计算),重复执行会产生大量冗余开销;方案二中view_project仅被处理一次,过滤条件也只执行一次。 - 降低数据扫描量:方案二会先过滤
view_project中is_open=1的有效数据,再与合并后的类别数据关联,JOIN操作的数据集规模更小;而方案一每次关联都要处理全量view_project数据后再过滤,数据处理量更大。 - 优化器友好性:主流数据库优化器对“先合并子数据集再关联主表”的逻辑支持更完善,更容易生成高效执行计划,避免重复解析视图、重复执行关联逻辑。
当然,最终性能需结合数据库类型、视图具体定义、索引配置等实际情况验证,但从理论逻辑和常规业务场景来看,方案二的效率优势显著。
内容的提问来源于stack exchange,提问作者user1579692
相关产品推荐
相关产品推荐

