SQL UNION优化:两种UNION ALL关联查询写法的性能适用场景咨询
两类同逻辑SQL写法的性能差异与适用场景
两种写法的结果完全对齐有一个核心前提:不存在跨拆分集的关联需求——也就是所有有效匹配只发生在A1与B1、A2与B2之间,不会出现A1关联B2、A2关联B1的情况,否则第二种写法会直接漏查数据,和第一种写法的结果不等价。
先UNION ALL合并再关联(第一种写法:(A1 UNION ALL A2) A JOIN (B1 UNION ALL B2) B ON ...)性能更优的场景
- 业务查询存在全局统一的过滤条件:比如全局需要按用户id范围、固定业务标签过滤,优化器可以自动把过滤谓词下推到两个拆分表的单表扫描环节,不需要在两套独立的JOIN逻辑里重复写相同的过滤规则,减少冗余逻辑
- 拆分表整体数据量较小:此时合并操作产生的临时集开销可以忽略不计,后续做关联时优化器可以直接选择最适配的通用JOIN算法,不需要对两次独立JOIN的输出结果再做一次UNION的序列化落盘/内存写入
- 需要长期维护统一的查询逻辑:也就是你提到的创建视图的场景——把A1/A2的UNION ALL逻辑固化为
VW_FULL_A视图,B1/B2的UNION ALL逻辑固化为VW_FULL_B视图,后续所有业务查询直接把视图当普通表使用即可,完全不需要感知底层的表拆分结构。后续如果新增A3、B3类的拆分表,只需要修改视图的定义,所有下游查询完全不需要改动,编码和长期维护成本远低于第二种写法。
先分别JOIN再UNION ALL(第二种写法:(A1 JOIN B1 ON ... WHERE ...) UNION ALL (A2 JOIN B2 ON ... WHERE ...))性能更优的场景
- 拆分表存在独立的、非统一的过滤条件:比如A1只需要过滤2023年的业务数据、A2只需要过滤2024年的业务数据,两个表的过滤逻辑完全独立,这种场景下先做各自带条件的JOIN,可以让过滤最早下推到单表扫描环节,避免先合并全量拆分数据再过滤产生的冗余中间结果
- 拆分表的关联查询可以利用本地独立的索引:比如A1和B1的关联键有本地联合覆盖索引、A2和B2的关联键也有独立的本地覆盖索引,先分别JOIN的方式可以直接通过索引扫描拿到所有需要的字段,不需要把全量数据先合并到临时集再做关联,减少临时存储的开销
- 两个拆分表的数据量差异极大:比如A2/B2占了整套拆分数据集99%的数据量,先分别JOIN的方式可以让优化器针对大表的关联单独估算成本、选择最优的JOIN算法,不会因为先合并体量差异极大的两个数据集,导致行数估算偏差,选错次优的关联执行计划。
你测试中碰到的两种写法执行计划、耗时完全一致的情况,本质是数据库优化器做了等价逻辑改写:当拆分表结构完全统一、过滤条件完全一致时,优化器会自动把「先合并再关联」的逻辑重写为「先关联再合并」的等价计划,因此最终执行效率没有任何差异。
内容的提问来源于stack exchange,提问作者Anh Duc Ng
相关产品推荐
相关产品推荐

