Почему тот же запрос с оператором UNION стоит намного дешевле, чем с UNION ALL? - PullRequest
0 голосов
/ 04 июня 2019

Стоимость моего тестового запроса составляет 910, если я использую UNION, и 46726, если я использую UNION ALL.Я использую 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 голосов
/ 04 июня 2019
  1. Термин «Стоимость» не всегда связан со временем, затраченным на выполнение запроса.«Стоимость» имеет более широкий смысл, чем просто время, затраченное на выполнение запроса.«Стоимость» включает в себя как физические, так и логические ресурсы.
  2. Оператор UNION выполняет две работы: поиск отдельных записей на основе выбранных столбцов и сортировку набора результатов.По сути, UNION сортирует набор результатов.Вот почему вы видите «SORT UNIQUE» как в EXPLAIN PLAN.
  3. UNION ALL не несет бремени поиска уникальных записей и их сортировки.Его работа самая простая.Добавить записи из 2-го запроса к 1-му запросу и вернуть результаты.Вот почему для извлечения требуется меньше времени по сравнению с оператором SELECT с оператором UNION.Очень важный момент, на который вам нужно обратить внимание, это физический и логический ресурс, используемый UNION ALL по сравнению с UNION.ВЫБОР ЗАЯВЛЕНИЯ 46726 3194117 198026200 970740819 46626
  4. В большинстве случаев Oracle DB находит способы сделать это более простым способом.Для Oracle DB будет лучше, если вы дадите ей запрос с помощью UNION ALL по сравнению с UNION.Вот почему время, занимаемое UNION, больше по сравнению с UNION ALL, хотя UNION ALL использует больше ресурсов, чем UNION.

UNION 0.078sec ---> Больше времени требуется для выполнения.СОЮЗ ----> Меньше использованных ресурсов.СТОИМОСТЬ КАРТЫ.БАЙТЫ CPU COST IO COST TEMP SPACE
ВЫБРАТЬ ЗАЯВЛЕНИЕ 910 4528 271695 214479428 905

UNION ALL 0.032sec ---> Меньше времени на выполнение.UNION ALL ---> Больше использованных ресурсов.СТОИМОСТЬ КАРТЫ.BYTES CPU COST IO COST TEMP SPACE ВЫБОР ЗАЯВЛЕНИЯ 46726 3194117 198026200 970740819 46626

Надеюсь, это прояснит ваши сомнения.

0 голосов
/ 04 июня 2019

разница между Union и Union all заключается в следующем.

UNION обеспечивает получение записей DISTINCT из обеих таблиц.UNION ALL извлекает все записи из обеих таблиц с дубликатами.

Причиной того, что ваш запрос на объединение всех запросов является более высокой, может быть, Oracle получает больше строк. Пожалуйста, проверьте план объяснения для обоих запросов, и вы можете увидетьчто запрос на объединение всех может выполнять больше операций, чем запрос на объединение.

...