Search code examples
oracle-databasequery-optimizationunionrownum

How to optimize an Oracle UNION ALL of two 3-sec queries that takes over 200 secs ... even with rownum


I am working to further optimize the following query. I have already had a lot of success optimizing the query up to this point, but now I am looking for help from others for ideas. I appreciate your help.

The following query takes over 200 seconds to complete yet the two individual WITH clause queries (receiving_1 and receiving_2) that make up the "UNION ALL" take less than 4 seconds each.

  • receiving_1 -- 58 recs in 3.4 secs; cost 295 (no UNION)
  • receiving_2 -- 0 recs in 3.8 secs; cost 295 (no UNION)
  • UNION ALL of 1+2 -- 58 recs in 203.1 secs; cost 300 (UNION ALL)

I was hoping "rownum" would help optimize the "UNION ALL", but it did not. This attempt was based on a note from AskTom --> Files --> SQLTechniques.zip (between 61 and 72)

When you have two queries that run light speed separately But not so together Generally a mixed “CBO/RBO” problem Use of RBO with a feature that kicks in the CBO Rownum can be a temporary fix till all things are CBO

NOTE: One optimization that avoids this issue is embedded replacement parameters or cursor parameters that greatly reduce the rows at key points in the query. However, because I need to run this query through a database link against a read-only database, the following options are not available for this query.

  • dbms_sql over database link: query is too long; dbs_sql does not accept a lob over database link; also DBAs don't allow the running of any PL/SQL in the read-only database.
  • pipelined function: pipelined function has known bug over database link between 19c and 11g so fails
  • sys_refcursor via PL/SQL: cursors are not supported over database links
  • set parameter values in PL/SQL package and use them in view: not allowed to execute any code in read-only database (I am still bugging the DBAs to allow this. This might be my best hope if I am not able to optimize the below query to run as a view.)

NOTE: In an attempt at providing a good test case with as little code as possible, the below SQL (4,584 chars, 88 line breaks) is a greatly simplified version of the actual SQL (93,683 chars, 2,014 line breaks) I am developing. The original SQL has already gone through several rounds of optimizations to bring the runtime down from over an hour to under 10 seconds. This latest challenge is that the SQL has to be rewritten as a view as opposed to a SQL file with embedded substitution parameters. The substitution parameters were key to the optimizations up to now. I am now refactoring the SQL to work as a view in Oracle 11gR2 to be called via a database link from Oracle 19c. A view has no parameters, obviously. The driving parameters (ledger, OU, period) will be WHERE clause conditions when querying the view.

Big picture: The actual SQL under development is an amalgamation of 6 report queries that share a lot of duplicated code. My work is to convert all six source report queries into an efficient extract for importing into a new database schema for reconciliation purposes.

with
gccs as ( 
select
       gcc.code_combination_id
    from apps.gl_code_combinations gcc
    where 1=1
      AND regexp_like(gcc.segment1,'^[0-9]{4}$') -- only include 4-digit numbers
      AND gcc.segment1 BETWEEN to_char('1500') and to_char('1504')
      AND regexp_like(gcc.segment3,'^[0-9]{4}$') -- only include 4-digit numbers
      AND (    gcc.segment3 BETWEEN to_char('5000') and to_char('5999')
            OR gcc.segment3 in ('6000','6002','6003','6004','6005','6006','6007','6008','6009','6010','6011','6012','6013','6014','6017','6018','6019','6020','6021','6022','6023','6024','6025','6026','6027','6028','6029','6030','6031','6032',
                                '6033','6034','6035','6036','6037','6038','6039','6040','6041','6042','6043','6044','6045','6046','6047','6048','6049','6050','6051','6052','6053','6054','6055','6056','6058','6060','6061','6062','6063','6064',
                                '6065','6066','6067','6068','6069','6070','6071','6072','6073','6074','6075','6076','6077','6084','6085','6086','6087','6088','6089','6090','6091','6092','6093','6094','6095','6096','6097','6098','6099','6100',
                                '6101','6102','6103','6104','6105','6106','6120','6121','6130','6131','6140','6150','6151','6155','6158','6162','6990','6991','6992','6993','6994','6995','6996','6997','6998'))
      AND regexp_like(gcc.segment6,'^[0-9]{4}$') -- only include 4-digit numbers
      AND gcc.segment6 BETWEEN to_char('3000') and to_char('4999')
) -- select count(*) code_combination_id from gccs;
,
base_query as (
    SELECT 
           gl.LEDGER_ID,
           hou.organization_id,
           gper.PERIOD_NAME,
           XAL.AE_HEADER_ID,
           XAL.AE_LINE_NUM,
           GJB.STATUS BATCH_STATUS,
           GJH.JE_CATEGORY,
           XAL.ACCOUNTING_CLASS_CODE,
           GJH.JE_SOURCE,
           GJH.JE_HEADER_ID,
           GJL.JE_LINE_NUM           
      FROM apps.gl_ledgers gl
            join apps.hr_operating_units         hou 
                on hou.set_of_books_id = gl.ledger_id
            join APPS.GL_JE_LINES               GJL 
                on exists (select null from gccs where gccs.CODE_COMBINATION_ID = GJL.CODE_COMBINATION_ID)
                   AND (nvl(gjl.stat_amount,0) <> 0 OR (NVL (gjl.accounted_dr, 0) - NVL (gjl.accounted_cr, 0)) <> 0)
            join APPS.GL_PERIODS                       gper
                on GJL.PERIOD_NAME = gper.PERIOD_NAME
            join APPS.GL_JE_HEADERS             GJH 
                on     GJH.JE_HEADER_ID = GJL.JE_HEADER_ID
                   AND GJH.PERIOD_NAME = gper.PERIOD_NAME
                   AND GJH.LEDGER_ID = gl.ledger_id
                   AND GJH.JE_SOURCE = 'Cost Management'
            join APPS.GL_JE_BATCHES             GJB 
                on GJB.JE_BATCH_ID = GJH.JE_BATCH_ID
            join APPS.GL_IMPORT_REFERENCES      GIR 
                on     GIR.JE_HEADER_ID = GJL.JE_HEADER_ID
                   AND GIR.JE_LINE_NUM = GJL.JE_LINE_NUM
            join APPS.XLA_AE_LINES              XAL 
                on     XAL.GL_SL_LINK_TABLE = GIR.GL_SL_LINK_TABLE
                   AND XAL.GL_SL_LINK_ID = GIR.GL_SL_LINK_ID
                   AND XAL.LEDGER_ID = gl.LEDGER_ID
),
receiving_1 as (
        select  distinct 
                        bq.LEDGER_ID,
                        bq.organization_id,
                        bq.period_name,
                        bq.AE_HEADER_ID,
                        bq.AE_LINE_NUM
          FROM base_query bq
         WHERE bq.BATCH_STATUS = 'P'
           AND UPPER(bq.JE_CATEGORY) = UPPER('Receiving')
), 
receiving_2 as (
        select   distinct
                        bq.LEDGER_ID,
                        bq.organization_id,
                        bq.period_name,
                        bq.AE_HEADER_ID,
                        bq.AE_LINE_NUM
          FROM base_query bq
         WHERE bq.ACCOUNTING_CLASS_CODE = 'INTRA'
           AND bq.BATCH_STATUS = 'P'
           AND UPPER(bq.JE_CATEGORY) = UPPER('Receiving')
),
receiving_all as (
    -- the use of "rownum" below sometimes helps to optimize "union all", but does not help in this query
    select rownum, x.* from receiving_1 x            -- 58 recs in   3.4 secs cost 295 (no UNION)
    union all                                        -- 58 recs in 203.1 secs cost 300 (UNION ALL)
    select rownum, x.* from receiving_2 x            -- 0 recs in 3.8 secs cost 295 (no UNION)
)
select count(*) 
    from receiving_all 
    where ledger_id = 2021 
      and organization_id = 82 
      and period_name = 'SEP-2020';

AUTOTRACE for receiving_1 part of query"

  COUNT(*)
----------
        58


Execution Plan
----------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                     | Name                           | Rows  | Bytes | Cost (%CPU)| Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                              |                                |     1 |    35 |   295   (1)|       |       |
|   1 |  SORT AGGREGATE                               |                                |     1 |    35 |            |       |       |
|   2 |   VIEW                                        |                                |     1 |    35 |   295   (1)|       |       |
|   3 |    COUNT                                      |                                |       |       |            |       |       |
|   4 |     VIEW                                      |                                |     1 |    35 |   295   (1)|       |       |
|   5 |      HASH UNIQUE                              |                                |     1 |   266 |   295   (1)|       |       |
|   6 |       NESTED LOOPS                            |                                |     1 |   266 |   294   (1)|       |       |
|   7 |        NESTED LOOPS                           |                                |     1 |   266 |   294   (1)|       |       |
|   8 |         NESTED LOOPS                          |                                |     1 |   237 |   236   (1)|       |       |
|   9 |          NESTED LOOPS                         |                                |     1 |   214 |   178   (1)|       |       |
|  10 |           NESTED LOOPS                        |                                |     1 |   207 |   176   (1)|       |       |
|  11 |            NESTED LOOPS                       |                                |     1 |   183 |   176   (1)|       |       |
|  12 |             NESTED LOOPS                      |                                |     1 |   152 |   173   (1)|       |       |
|  13 |              NESTED LOOPS                     |                                |     1 |   148 |   173   (1)|       |       |
|  14 |               NESTED LOOPS                    |                                |     1 |   123 |   172   (1)|       |       |
|  15 |                NESTED LOOPS                   |                                |     1 |   101 |   169   (1)|       |       |
|  16 |                 NESTED LOOPS                  |                                |     1 |    97 |   169   (1)|       |       |
|  17 |                  NESTED LOOPS                 |                                |     1 |    53 |   167   (1)|       |       |
|  18 |                   SORT UNIQUE                 |                                |     1 |    21 |    22   (0)|       |       |
|  19 |                    TABLE ACCESS BY INDEX ROWID| GL_CODE_COMBINATIONS           |     1 |    21 |    22   (0)|       |       |
|  20 |                     INDEX RANGE SCAN          | GL_CODE_COMBINATIONS_N1        |   117 |       |     8   (0)|       |       |
|  21 |                   TABLE ACCESS BY INDEX ROWID | GL_JE_LINES                    |    16 |   512 |   144   (0)|       |       |
|  22 |                    INDEX RANGE SCAN           | GL_JE_LINES_N1                 |   319 |       |     4   (0)|       |       |
|  23 |                  TABLE ACCESS BY INDEX ROWID  | GL_JE_HEADERS                  |     1 |    44 |     2   (0)|       |       |
|  24 |                   INDEX UNIQUE SCAN           | GL_JE_HEADERS_U1               |     1 |       |     1   (0)|       |       |
|  25 |                 INDEX UNIQUE SCAN             | GL_LEDGERS_U2                  |     1 |     4 |     0   (0)|       |       |
|  26 |                TABLE ACCESS BY INDEX ROWID    | HR_ORGANIZATION_INFORMATION    |     1 |    22 |     3   (0)|       |       |
|  27 |                 INDEX RANGE SCAN              | HR_ORGANIZATION_INFORMATIO_FK1 |    30 |       |     1   (0)|       |       |
|  28 |               INDEX RANGE SCAN                | GL_PERIODS_U1                  |     1 |    25 |     1   (0)|       |       |
|  29 |              INDEX UNIQUE SCAN                | HR_ORGANIZATION_UNITS_PK       |     1 |     4 |     0   (0)|       |       |
|  30 |             TABLE ACCESS BY INDEX ROWID       | HR_ORGANIZATION_INFORMATION    |     1 |    31 |     3   (0)|       |       |
|  31 |              INDEX RANGE SCAN                 | HR_ORGANIZATION_INFORMATIO_FK2 |     2 |       |     1   (0)|       |       |
|  32 |            INDEX UNIQUE SCAN                  | HR_ALL_ORGANIZATION_UNTS_TL_PK |     1 |    24 |     0   (0)|       |       |
|  33 |           TABLE ACCESS BY INDEX ROWID         | GL_JE_BATCHES                  |     1 |     7 |     2   (0)|       |       |
|  34 |            INDEX UNIQUE SCAN                  | GL_JE_BATCHES_U1               |     1 |       |     1   (0)|       |       |
|  35 |          TABLE ACCESS BY INDEX ROWID          | GL_IMPORT_REFERENCES           |   105 |  2415 |    58   (0)|       |       |
|  36 |           INDEX RANGE SCAN                    | GL_IMPORT_REFERENCES_N1        |   105 |       |     3   (0)|       |       |
|  37 |         PARTITION LIST ALL                    |                                |     1 |       |    57   (0)|     1 |    19 |
|  38 |          INDEX RANGE SCAN                     | XLA_AE_LINES_N4                |     1 |       |    57   (0)|     1 |    19 |
|  39 |        TABLE ACCESS BY LOCAL INDEX ROWID      | XLA_AE_LINES                   |     1 |    29 |    58   (0)|     1 |     1 |
-------------------------------------------------------------------------------------------------------------------------------------

Note
-----
   - 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
         99  recursive calls
          0  db block gets
    3500320  consistent gets
          0  physical reads
        116  redo size
        346  bytes sent via SQL*Net to client
       4388  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

AUTOTRACE for receiving_2 part of query:

  COUNT(*)
----------
        0


Execution Plan
----------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                     | Name                           | Rows  | Bytes | Cost (%CPU)| Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                              |                                |     1 |    35 |   295   (1)|       |       |
|   1 |  SORT AGGREGATE                               |                                |     1 |    35 |            |       |       |
|   2 |   VIEW                                        |                                |     1 |    35 |   295   (1)|       |       |
|   3 |    COUNT                                      |                                |       |       |            |       |       |
|   4 |     VIEW                                      |                                |     1 |    35 |   295   (1)|       |       |
|   5 |      HASH UNIQUE                              |                                |     1 |   279 |   295   (1)|       |       |
|   6 |       NESTED LOOPS                            |                                |     1 |   279 |   294   (1)|       |       |
|   7 |        NESTED LOOPS                           |                                |     1 |   279 |   294   (1)|       |       |
|   8 |         NESTED LOOPS                          |                                |     1 |   272 |   292   (1)|       |       |
|   9 |          NESTED LOOPS                         |                                |     1 |   230 |   234   (1)|       |       |
|  10 |           NESTED LOOPS                        |                                |     1 |   207 |   176   (1)|       |       |
|  11 |            NESTED LOOPS                       |                                |     1 |   183 |   176   (1)|       |       |
|  12 |             NESTED LOOPS                      |                                |     1 |   152 |   173   (1)|       |       |
|  13 |              NESTED LOOPS                     |                                |     1 |   148 |   173   (1)|       |       |
|  14 |               NESTED LOOPS                    |                                |     1 |   126 |   170   (1)|       |       |
|  15 |                NESTED LOOPS                   |                                |     1 |   122 |   170   (1)|       |       |
|  16 |                 NESTED LOOPS                  |                                |     1 |    97 |   169   (1)|       |       |
|  17 |                  NESTED LOOPS                 |                                |     1 |    53 |   167   (1)|       |       |
|  18 |                   SORT UNIQUE                 |                                |     1 |    21 |    22   (0)|       |       |
|  19 |                    TABLE ACCESS BY INDEX ROWID| GL_CODE_COMBINATIONS           |     1 |    21 |    22   (0)|       |       |
|  20 |                     INDEX RANGE SCAN          | GL_CODE_COMBINATIONS_N1        |   117 |       |     8   (0)|       |       |
|  21 |                   TABLE ACCESS BY INDEX ROWID | GL_JE_LINES                    |    16 |   512 |   144   (0)|       |       |
|  22 |                    INDEX RANGE SCAN           | GL_JE_LINES_N1                 |   319 |       |     4   (0)|       |       |
|  23 |                  TABLE ACCESS BY INDEX ROWID  | GL_JE_HEADERS                  |     1 |    44 |     2   (0)|       |       |
|  24 |                   INDEX UNIQUE SCAN           | GL_JE_HEADERS_U1               |     1 |       |     1   (0)|       |       |
|  25 |                 INDEX RANGE SCAN              | GL_PERIODS_U1                  |     1 |    25 |     1   (0)|       |       |
|  26 |                INDEX UNIQUE SCAN              | GL_LEDGERS_U2                  |     1 |     4 |     0   (0)|       |       |
|  27 |               TABLE ACCESS BY INDEX ROWID     | HR_ORGANIZATION_INFORMATION    |     1 |    22 |     3   (0)|       |       |
|  28 |                INDEX RANGE SCAN               | HR_ORGANIZATION_INFORMATIO_FK1 |    30 |       |     1   (0)|       |       |
|  29 |              INDEX UNIQUE SCAN                | HR_ORGANIZATION_UNITS_PK       |     1 |     4 |     0   (0)|       |       |
|  30 |             TABLE ACCESS BY INDEX ROWID       | HR_ORGANIZATION_INFORMATION    |     1 |    31 |     3   (0)|       |       |
|  31 |              INDEX RANGE SCAN                 | HR_ORGANIZATION_INFORMATIO_FK2 |     2 |       |     1   (0)|       |       |
|  32 |            INDEX UNIQUE SCAN                  | HR_ALL_ORGANIZATION_UNTS_TL_PK |     1 |    24 |     0   (0)|       |       |
|  33 |           TABLE ACCESS BY INDEX ROWID         | GL_IMPORT_REFERENCES           |   105 |  2415 |    58   (0)|       |       |
|  34 |            INDEX RANGE SCAN                   | GL_IMPORT_REFERENCES_N1        |   105 |       |     3   (0)|       |       |
|  35 |          PARTITION LIST ALL                   |                                |     1 |    42 |    58   (0)|     1 |    19 |
|  36 |           TABLE ACCESS BY LOCAL INDEX ROWID   | XLA_AE_LINES                   |     1 |    42 |    58   (0)|     1 |    19 |
|  37 |            INDEX RANGE SCAN                   | XLA_AE_LINES_N4                |     1 |       |    57   (0)|     1 |    19 |
|  38 |         INDEX UNIQUE SCAN                     | GL_JE_BATCHES_U1               |     1 |       |     1   (0)|       |       |
|  39 |        TABLE ACCESS BY INDEX ROWID            | GL_JE_BATCHES                  |     1 |     7 |     2   (0)|       |       |
-------------------------------------------------------------------------------------------------------------------------------------

Note
-----
   - 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
         99  recursive calls
          0  db block gets
    3451912  consistent gets
          0  physical reads
          0  redo size
        345  bytes sent via SQL*Net to client
       4385  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

AUTOTRACE for UNION ALL of full query that includes both request_1 and request_2

  COUNT(*)
----------
        58


Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name                           | Rows  | Bytes | Cost (%CPU)| Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |                                |     1 |    35 |   300   (1)|       |       |
|   1 |  TEMP TABLE TRANSFORMATION                 |                                |       |       |            |       |       |
|   2 |   LOAD AS SELECT                           | SYS_TEMP_0FD9D6767_FC3F7B00    |       |       |            |       |       |
|   3 |    NESTED LOOPS                            |                                |     1 |   279 |   294   (1)|       |       |
|   4 |     NESTED LOOPS                           |                                |     1 |   279 |   294   (1)|       |       |
|   5 |      NESTED LOOPS                          |                                |     1 |   237 |   236   (1)|       |       |
|   6 |       NESTED LOOPS                         |                                |     1 |   214 |   178   (1)|       |       |
|   7 |        NESTED LOOPS                        |                                |     1 |   207 |   176   (1)|       |       |
|   8 |         NESTED LOOPS                       |                                |     1 |   183 |   176   (1)|       |       |
|   9 |          NESTED LOOPS                      |                                |     1 |   152 |   173   (1)|       |       |
|  10 |           NESTED LOOPS                     |                                |     1 |   148 |   173   (1)|       |       |
|  11 |            NESTED LOOPS                    |                                |     1 |   126 |   170   (1)|       |       |
|  12 |             NESTED LOOPS                   |                                |     1 |   122 |   170   (1)|       |       |
|  13 |              NESTED LOOPS                  |                                |     1 |    78 |   168   (1)|       |       |
|  14 |               NESTED LOOPS                 |                                |     1 |    53 |   167   (1)|       |       |
|  15 |                SORT UNIQUE                 |                                |     1 |    21 |    22   (0)|       |       |
|  16 |                 TABLE ACCESS BY INDEX ROWID| GL_CODE_COMBINATIONS           |     1 |    21 |    22   (0)|       |       |
|  17 |                  INDEX RANGE SCAN          | GL_CODE_COMBINATIONS_N1        |   117 |       |     8   (0)|       |       |
|  18 |                TABLE ACCESS BY INDEX ROWID | GL_JE_LINES                    |    16 |   512 |   144   (0)|       |       |
|  19 |                 INDEX RANGE SCAN           | GL_JE_LINES_N1                 |   319 |       |     4   (0)|       |       |
|  20 |               INDEX RANGE SCAN             | GL_PERIODS_U1                  |     1 |    25 |     1   (0)|       |       |
|  21 |              TABLE ACCESS BY INDEX ROWID   | GL_JE_HEADERS                  |     1 |    44 |     2   (0)|       |       |
|  22 |               INDEX UNIQUE SCAN            | GL_JE_HEADERS_U1               |     1 |       |     1   (0)|       |       |
|  23 |             INDEX UNIQUE SCAN              | GL_LEDGERS_U2                  |     1 |     4 |     0   (0)|       |       |
|  24 |            TABLE ACCESS BY INDEX ROWID     | HR_ORGANIZATION_INFORMATION    |     1 |    22 |     3   (0)|       |       |
|  25 |             INDEX RANGE SCAN               | HR_ORGANIZATION_INFORMATIO_FK1 |    30 |       |     1   (0)|       |       |
|  26 |           INDEX UNIQUE SCAN                | HR_ORGANIZATION_UNITS_PK       |     1 |     4 |     0   (0)|       |       |
|  27 |          TABLE ACCESS BY INDEX ROWID       | HR_ORGANIZATION_INFORMATION    |     1 |    31 |     3   (0)|       |       |
|  28 |           INDEX RANGE SCAN                 | HR_ORGANIZATION_INFORMATIO_FK2 |     2 |       |     1   (0)|       |       |
|  29 |         INDEX UNIQUE SCAN                  | HR_ALL_ORGANIZATION_UNTS_TL_PK |     1 |    24 |     0   (0)|       |       |
|  30 |        TABLE ACCESS BY INDEX ROWID         | GL_JE_BATCHES                  |     1 |     7 |     2   (0)|       |       |
|  31 |         INDEX UNIQUE SCAN                  | GL_JE_BATCHES_U1               |     1 |       |     1   (0)|       |       |
|  32 |       TABLE ACCESS BY INDEX ROWID          | GL_IMPORT_REFERENCES           |   105 |  2415 |    58   (0)|       |       |
|  33 |        INDEX RANGE SCAN                    | GL_IMPORT_REFERENCES_N1        |   105 |       |     3   (0)|       |       |
|  34 |      PARTITION LIST ALL                    |                                |     1 |       |    57   (0)|     1 |    19 |
|  35 |       INDEX RANGE SCAN                     | XLA_AE_LINES_N4                |     1 |       |    57   (0)|     1 |    19 |
|  36 |     TABLE ACCESS BY LOCAL INDEX ROWID      | XLA_AE_LINES                   |     1 |    42 |    58   (0)|     1 |     1 |
|  37 |   SORT AGGREGATE                           |                                |     1 |    35 |            |       |       |
|  38 |    VIEW                                    |                                |     2 |    70 |     6  (34)|       |       |
|  39 |     UNION-ALL                              |                                |       |       |            |       |       |
|  40 |      COUNT                                 |                                |       |       |            |       |       |
|  41 |       VIEW                                 |                                |     1 |    35 |     3  (34)|       |       |
|  42 |        HASH UNIQUE                         |                                |     1 |    44 |     3  (34)|       |       |
|  43 |         VIEW                               |                                |     1 |    44 |     2   (0)|       |       |
|  44 |          TABLE ACCESS FULL                 | SYS_TEMP_0FD9D6767_FC3F7B00    |     1 |    74 |     2   (0)|       |       |
|  45 |      COUNT                                 |                                |       |       |            |       |       |
|  46 |       VIEW                                 |                                |     1 |    35 |     3  (34)|       |       |
|  47 |        HASH UNIQUE                         |                                |     1 |    61 |     3  (34)|       |       |
|  48 |         VIEW                               |                                |     1 |    61 |     2   (0)|       |       |
|  49 |          TABLE ACCESS FULL                 | SYS_TEMP_0FD9D6767_FC3F7B00    |     1 |    74 |     2   (0)|       |       |
----------------------------------------------------------------------------------------------------------------------------------

Note
-----
   - 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
        766  recursive calls
      83076  db block gets
  270487689  consistent gets
      81660  physical reads
        676  redo size
        346  bytes sent via SQL*Net to client
       4582  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed


Solution

  • As I don't know the underlying tables, their structure and their data, I can only guess. Having said that, I'd try the following things (not knowing if any of the steps are helpful or not!):

    1. remove the rownum from receiving_all

    2. add the where clause from the main query to each of the subqueries in receiving_all. The optimizer might be able to infer this, but I am not sure.

    3. change union all to union in receiving_all and remove the distinct from receiving_1 and receiving_2

    4. receiving_2 seems to be included in receiving_2?

    5. If 4. is not the case, I would combine both into a single query with WHERE UPPER(bq.JE_CATEGORY) = UPPER('Receiving') AND ( (<conditions for 1>) OR (<conditions for 2>) )

    6. I would try if UPPER(bq.JE_CATEGORY) can be avoided. Functions prevent index access.

    7. In case you can create tables, I'd unroll the values of gccs into two tables, one for segment_1, and another table for segment_2.

    8. If 7. is not an option, I'd add the hint select /*+ materialize */ gcc.code_combination_id to gcc.

    I'm very curious to see which suggestion has any positive impact...