为什么用UNION运算符进行相同的查询要比使用UNION ALL便宜得多?

时间:2019-06-04 13:07:22

标签: plsql union union-all

如果我使用UNION,则测试查询的成本为910,如果使用UNION ALL,则成本为46726。我使用PL / SQLDeveloper。据我了解,UNION ALL应该花费更少,因为它不会花费时间删除重复的行。有人可以向我解释为什么用UNION查询更快吗?

My test query is:
       SELECT RELATED_ORDR.ORDR_ID ID
              ,RELATED_ORDR.ORDR_ID
              ,EXT_TYPE TYPE
              ,DECODE(RELATION, 1, GOR_CONTINGENCY, CONTINGENCY) CONTINGENCY_TYPE
              ,RELATION
              ,DECODE(SIGN(ORDR_QTY),1,'B',-1,'S') BSS
              ,ORDR_QTY QUANTITY
              ,FXRE2_ORDER_AUDIT_REPORT.getOrderStatus(EXT_STATUS) STATUS
              ,STATUS_DT DT
              ,TRADE_ID TICKET
              ,CASE WHEN EXT_TYPE IN ('OR', 'CR', 'RE', 'RTE') THEN RATE2
                    ELSE RATE
               END RATE
              ,OFFER_ID
          FROM
              (SELECT DISTINCT RO.ID ORDR_ID
                              ,RO.CONTINGENCY_TYPE CONTINGENCY
                              ,DECODE(RO.ID, GOR.ORDR_ID_PRIMARY, 1,
                                      DECODE(RO.CONTINGENCY_ID, GOR.CONTINGENCY_ID, 3,
                                             DECODE(RO.CONTINGENCY_ID, GOR.ORDR_ID, 2,
                                                    DECODE(RO.ORDR_ID_PRIMARY, GOR.ORDR_ID, 2)))) RELATION
                              ,GOR.CONTINGENCY_TYPE GOR_CONTINGENCY
                 FROM /*GIVEN_ORDR GOR --GIVEN*/
                      (SELECT to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,1)) as ORDR_ID
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,2)) as ORDR_ID_PRIMARY
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,3)) as CONTINGENCY_ID
                             ,          regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,4)  as CONTINGENCY_TYPE
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,5)) as ACCT_ID
                         FROM dual t) GOR --GIVEN
                      ,ORDR_HIST RO --RELATED/LINKED
                WHERE GOR.ACCT_ID = RO.ACCT_ID
                  AND RO.ID != GOR.ORDR_ID-- NOT GIVEN ORDR
                  AND RO.STATUS_DT IS NOT NULL
                  AND (RO.ID = GOR.ORDR_ID_PRIMARY
                       OR RO.CONTINGENCY_ID = GOR.CONTINGENCY_ID
                       OR RO.CONTINGENCY_ID = GOR.ORDR_ID
                       OR RO.ORDR_ID_PRIMARY = GOR.ORDR_ID)) RELATED_ORDR
              ,ORDR_HIST
         WHERE ORDR_HIST.ID = (SELECT MAX(ID) FROM ORDR_HIST WHERE ID = RELATED_ORDR.ORDR_ID)
         UNION ALL
        SELECT RELATED_ORDR.ORDR_ID ID -- just for compatibility, it is not used
              ,RELATED_ORDR.ORDR_ID
              ,EXT_TYPE TYPE
              ,DECODE(RELATION, 1, GOR_CONTINGENCY, CONTINGENCY) CONTINGENCY_TYPE
              ,RELATION
              ,DECODE(SIGN(ORDR_QTY),1,'B',-1,'S') BSS
              ,ORDR_QTY QUANTITY
              ,FXRE2_ORDER_AUDIT_REPORT.getOrderStatus(EXT_STATUS) STATUS
              ,STATUS_DT DT
              ,TRADE_ID TICKET
              ,CASE WHEN EXT_TYPE IN ('OR', 'CR', 'RE', 'RTE') THEN RATE2
                    ELSE RATE
               END RATE
              ,OFFER_ID
          FROM
              (SELECT DISTINCT RO.ID ORDR_ID
                              ,RO.CONTINGENCY_TYPE CONTINGENCY
                              ,DECODE(RO.ID, GOR.ORDR_ID_PRIMARY, 1,
                                      DECODE(RO.CONTINGENCY_ID, GOR.CONTINGENCY_ID, 3,
                                             DECODE(RO.CONTINGENCY_ID, GOR.ORDR_ID, 2,
                                                    DECODE(RO.ORDR_ID_PRIMARY, GOR.ORDR_ID, 2)))) RELATION
                              ,GOR.CONTINGENCY_TYPE GOR_CONTINGENCY
                 FROM /*GIVEN_ORDR GOR --GIVEN*/
                      (SELECT to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,1)) as ORDR_ID
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,2)) as ORDR_ID_PRIMARY
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,3)) as CONTINGENCY_ID
                             ,          regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,4)  as CONTINGENCY_TYPE
                             ,to_number(regexp_substr('21153473;21151187;21151187;3;5240435','[^;]+',1,5)) as ACCT_ID
                         FROM dual t) GOR --GIVEN
                      ,ORDR_HIST RO --RELATED/LINKED
                WHERE GOR.ACCT_ID = RO.ACCT_ID
                  AND RO.ID != GOR.ORDR_ID-- NOT GIVEN ORDR
                  AND RO.STATUS_DT IS NOT NULL
                  AND (RO.ID = GOR.ORDR_ID_PRIMARY
                       OR RO.CONTINGENCY_ID = GOR.CONTINGENCY_ID
                       OR RO.CONTINGENCY_ID = GOR.ORDR_ID
                       OR RO.ORDR_ID_PRIMARY = GOR.ORDR_ID)) RELATED_ORDR
              ,ORDR
         WHERE ORDR.ID = (SELECT MAX(ID) FROM ORDR_HIST WHERE ID = RELATED_ORDR.ORDR_ID)                  
         ORDER BY ID;}

The plans of 2 queries are:
UNION 0.078sec                 COST    CARD.   BYTES   CPU COST      IO COST   TEMP SPACE   
SELECT STATEMENT                910 4528    271695  214479428   905 
UNION ALL 0.032sec
SELECT STATEMENT                46726   3194117 198026200 970740819 46626   


SELECT STATEMENT                910 4528    271695  214479428   905 

 SORT UNIQUE            909 4528    271695  172294190   905 
  UNION-ALL                             
   HASH JOIN            551 1   75  45895432    550 
    NESTED LOOPS            551 1   75  45895432    550 
     NESTED LOOPS           551 1   75  45895432    550 
      STATISTICS COLLECTOR                              
       NESTED LOOPS         452 1   33  45187910    451 
        VIEW    U1R2_DEV        353 1   20  44482687    352 
         HASH UNIQUE            353 1   18  44482687    352 
          NESTED LOOPS          352 1   18  4775046 352 
           FAST DUAL            2   1       7271    2   
           PARTITION RANGE ALL          350 1   18  4767775 350 
            TABLE ACCESS BY LOCAL INDEX ROWID BATCHED   U1R2    ORDR_HIST   350 1   18  4767775 350 
             INDEX RANGE SCAN   U1R2    OH_ACCT_ID_IDX  101 1285        977115  101 
        VIEW PUSHED PREDICATE   SYS VW_SQ_1 99  1   13  705223  99  
         FILTER                             
          SORT AGGREGATE                1   6           
           PARTITION RANGE ALL          99  1   6   705223  99  
            INDEX RANGE SCAN    U1R2    ORDR_HIST2_ACCT_ID  99  1   6   705223  99  
      PARTITION RANGE ALL           98  1       698951  98  
       INDEX RANGE SCAN U1R2    ORDR_HIST2_ACCT_ID  98  1       698951  98  
     TABLE ACCESS BY LOCAL INDEX ROWID  U1R2    ORDR_HIST   99  1   42  707523  99  
    PARTITION RANGE ALL         99  1   42  707523  99  
     TABLE ACCESS FULL  U1R2    ORDR_HIST   99  1   42  707523  99  
   NESTED LOOPS         356 1   60  44506492    355 
    NESTED LOOPS            356 1   60  44506492    355 
     VIEW   U1R2_DEV        353 1   20  44482687    352 
      HASH UNIQUE           353 1   18  44482687    352 
       NESTED LOOPS         352 1   18  4775046 352 
        FAST DUAL           2   1       7271    2   
        PARTITION RANGE ALL         350 1   18  4767775 350 
         TABLE ACCESS BY LOCAL INDEX ROWID BATCHED  U1R2    ORDR_HIST   350 1   18  4767775 350 
          INDEX RANGE SCAN  U1R2    OH_ACCT_ID_IDX  101 1285        977115  101 
     INDEX RANGE SCAN   U1R2    ORDR_AIM    2   1       15293   2   
      PARTITION RANGE ALL MIN/MAX               1   6           
       SORT AGGREGATE               1   6           
        FIRST ROW           99  1   6   705223  99  
         INDEX RANGE SCAN (MIN/MAX) U1R2    ORDR_HIST2_ACCT_ID  99  1   6   705223  99  
    TABLE ACCESS BY INDEX ROWID U1R2    ORDR    3   1   40  23804   3   


UNION ALL 0.032sec

SELECT STATEMENT                46726   3194117 198026200   3970740819  46626   
 SORT ORDER BY          808 3194117 198026200   89696701    806 269771000
  UNION-ALL                             
   NESTED LOOPS         452 1   62  45190210    451 
    NESTED LOOPS            452 1   62  45190210    451 
     VIEW   U1R2_DEV        353 1   20  44482687    352 
      HASH UNIQUE           353 1   18  44482687    352 
       NESTED LOOPS         352 1   18  4775046 352 
        FAST DUAL           2   1       7271    2   
        PARTITION RANGE ALL         350 1   18  4767775 350 
         TABLE ACCESS BY LOCAL INDEX ROWID BATCHED  U1R2    ORDR_HIST   350 1   18  4767775 350 
          INDEX RANGE SCAN  U1R2    OH_ACCT_ID_IDX  101 1285        977115  101 
     PARTITION RANGE ALL            98  1       698951  98  
      INDEX RANGE SCAN  U1R2    ORDR_HIST2_ACCT_ID  98  1       698951  98  
       PARTITION RANGE ALL MIN/MAX              1   6           
        SORT AGGREGATE              1   6           
         FIRST ROW          99  1   6   705223  99  
          INDEX RANGE SCAN (MIN/MAX)    U1R2    ORDR_HIST2_ACCT_ID  99  1   6   705223  99  
    TABLE ACCESS BY LOCAL INDEX ROWID   U1R2    ORDR_HIST   99  1   42  707523  99  
   NESTED LOOPS         356 1   60  44506492    355 
    NESTED LOOPS            356 1   60  44506492    355 
     VIEW   U1R2_DEV        353 1   20  44482687    352 
      HASH UNIQUE           353 1   18  44482687    352 
       NESTED LOOPS         352 1   18  4775046 352 
        FAST DUAL           2   1       7271    2   
        PARTITION RANGE ALL         350 1   18  4767775 350 
         TABLE ACCESS BY LOCAL INDEX ROWID BATCHED  U1R2    ORDR_HIST   350 1   18  4767775 350 
          INDEX RANGE SCAN  U1R2    OH_ACCT_ID_IDX  101 1285        977115  101 
     INDEX RANGE SCAN   U1R2    ORDR_AIM    2   1       15293   2   
      PARTITION RANGE ALL MIN/MAX               1   6           
       SORT AGGREGATE               1   6           
        FIRST ROW           99  1   6   705223  99  
         INDEX RANGE SCAN (MIN/MAX) U1R2    ORDR_HIST2_ACCT_ID  99  1   6   705223  99  
    TABLE ACCESS BY INDEX ROWID U1R2    ORDR    3   1   40  23804   3

2 个答案:

答案 0 :(得分:0)

Union和Union all之间的区别如下。

UNION确保您从两个表中都获得DISTINCT记录。 UNION ALL从两个表中提取出所有重复的记录。

您的全部查询成本较高的原因可能是Oracle正在获取更多行, 请检查两个查询的解释计划,您可能会发现“并集所有查询”可能比并集查询做更多的处理。

答案 1 :(得分:0)

  1. 术语“成本”并不总是与查询执行所花费的时间相关联。 “成本”具有更广泛的含义,而不仅仅是执行查询所花费的时间。 “成本”包括物理资源和逻辑资源。
  2. UNION运算符完成两项工作:根据SELECTED列查找不同的记录,并对结果集进行排序。基本上,UNION对结果集进行排序。这就是为什么您会在“说明计划”中看到“ SORT UNIQUE”的原因。
  3. UNION ALL没有查找唯一记录并对其进行排序的负担。它的工作是最简单的。将第二个查询的记录附加到第一个查询,然后返回结果。这就是为什么与带有UNION运算符的SELECT相比,检索时间更少的原因。与UNION相比,您需要查看的非常重要的一点是UNION ALL使用的物理和逻辑资源。 选择语句46726 3194117 198026200 970740819 46626
  4. 在大多数情况下,Oracle DB找到了一种更简单的方式来做事情。对于Oracle DB,如果您使用UNION ALL而不是UNION进行查询,它将更加快乐。这就是为什么与UNION ALL相比,UNION花费的时间要多于UNION ALL。

UNION 0.078sec --->执行需要更多时间。 UNION ---->使用的资源较少。 成本卡。字节CPU成本IO成本温度空间
选择语句910 4528 271695 214479428 905

UNION ALL 0.032sec --->减少执行时间。 UNION ALL --->使用了更多的资源。 成本卡。字节CPU成本IO成本温度空间 选择语句46726 3194117 198026200 970740819 46626

希望这可以澄清您的疑问。