如何减少 Oracle 数据库中查询的执行时间?

How to reduce execution time of my query in Oracle database?

我从不同的视图和函数中提取了那些 table 名称。执行时间需要 1 天以上才能完成。我的目标是将时间从 1 天减少到 30 分钟或更短。我的老板建议我微调视图下视图中的所有查询。关于如何减少时间的任何提示或建议?

查询

SELECT to_char(con.originalstartdate, 'MM/DD/YY') TXNDATEIN,
       to_char(con.originalstartdate, 'HH24:MI:SS') TIMEIN,
       to_char(CON.LASTACTIVITYDATE, 'MM/DD/YY') TXNDATEOUT,
       to_char(con.lastactivitydate, 'HH24:MI:SS') TIMEOUT,
       pack.mes_packagename, prodfam.productfamilyname,
       con.containername RELATEDCONTNAME, shd.qty QTYIN, 
       con.qty QTYOUT, qtyhist.qty, lossrea.lossreasonname,
       resdef.resourcename WS, emp.fullname EMPLOYEENAME,
       oprtn.operationname, hml.txndate,
       (   SELECT GET_DIFFUSION_CONTAINER_APP(con.containername) 
           FROM DUAL) AS DIFFUSION
FROM container con, package pack, productfamily prodfam, 
     lossreason lossrea, resourcedef resdef, employee emp, 
     operation oprtn, qtyhistory qtyhist, splithistorydetails shd,
     historymainline hml
where con.lastactivitydate >=  to_date('06/23/2014 6:00:00', 'MM/DD/YYYY HH:MI:SS')
and con.lastactivitydate < to_date('06/24/2014 6:00:00', 'MM/DD/YYYY HH:MI:SS')
and hml.txndate >= to_date('06/23/2014 6:00:00', 'MM/DD/YYYY HH:MI:SS') 
and to_char(hml.txndate, 'MM/DD/YYYY') <= to_char(con.lastactivitydate, 'MM/DD/YYYY')
ORDER BY RELATEDCONTNAME;

原始查询

SET ECHO OFF
SET COLSEP ,
SET PAGES 0
SET LINESIZE 1000
SET TRIMSPOOL ON
SET FEEDBACK OFF
SET UNDERLINE OFF
SET VER OFF

column NCURRENT NEW_VALUE VFILE NOPRINT
column NYEST NEW_VALUE VFILE2  
column NNOW NEW_VALUE VFILE3  
column NCURRENTYEAR NEW_VALUE VFILE4  
column WEEKCODE NEW_VALUE VFILE5 

select to_char(sysdate -2 , 'RRRR-MM-DD')||' 06:00:00' NYEST
--select '2013-05-18 12:00:00' NYEST
from dual;

select to_char(sysdate-1, 'RRRR-MM-DD')||' 06:00:00' NNOW
--select '2013-05-19 12:00:00' NNOW
from dual;

select to_char(sysdate, 'RRRR') NCURRENTYEAR
from dual;

select 'FName_'||to_char(sysdate-1, 'MONDDRRRR')||'.csv' NCURRENT
from dual;

spool [Filepath];

select 
       TXNDATEIN||','||TIMEIN||','||TXNDATEOUT||','||TIMEOUT||','||  MES_PACKAGENAME||','||MINICOMPANYNAME||','||PRODUCTFAMILYNAME||','||RELATEDCONTNAME||','||
       QTYIN||','||QTYOUT||','||QTY||','||LOSSREASONNAME||','||WS||','||REPLACE(EMPLOYEENAME,',',' ')||','||OPERATIONNAME||','||
       (SELECT GET_DIFFUSION_CONTAINER_APP(RELATEDCONTNAME) FROM DUAL) AS DIFFUSION
from 
 vw_power_overallyield_batchfe
where 
txndate >=  to_date('&&VFILE2', 'yyyy-mm-dd HH24:MI:SS')
and txndate < to_date('&&VFILE3', 'yyyy-mm-dd HH24:MI:SS')
and scraptxndate >= to_date('&&VFILE2', 'yyyy-mm-dd HH24:MI:SS') 
and to_char(scraptxndate, 'MM/DD/YY') <= TXNDATEOUT 
ORDER BY RELATEDCONTNAME;
spool off;
exit

解释计划

    PLAN_TABLE_OUTPUT

----------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)|
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                          |    18E|    15E|       |    18E  (0)|
|   1 |  FAST DUAL                             |                          |     1 |       |       |     2   (0)|
|   2 |  SORT ORDER BY                         |                          |    18E|    15E|    15E|    18E  (0)|
|   3 |   MERGE JOIN CARTESIAN                 |                          |    18E|    15E|       |    18E  (0)|
|   4 |    MERGE JOIN CARTESIAN                |                          |    18E|    15E|       |    18E  (0)|
|   5 |     MERGE JOIN CARTESIAN               |                          |    18E|    15E|       |   204P  (1)|
|   6 |      MERGE JOIN CARTESIAN              |                          |    54T|  5457T|       |   521G  (1)|
|   7 |       MERGE JOIN CARTESIAN             |                          |    84G|  7259G|       |   942M  (1)|
|   8 |        MERGE JOIN CARTESIAN            |                          |    17M|  1258M|       |   210K  (1)|
|   9 |         MERGE JOIN CARTESIAN           |                          |  8713 |   536K|       |    87   (3)|
|  10 |          MERGE JOIN CARTESIAN          |                          |    16 |   816 |       |    16  (13)|
|  11 |           MERGE JOIN                   |                          |     1 |    43 |       |    13  (16)|
|  12 |            SORT JOIN                   |                          |     3 |    24 |       |     5  (20)|
|* 13 |             INDEX RANGE SCAN           | HISTORYMLBYTXNDATEANDRES |     3 |    24 |       |     4   (0)|
|* 14 |            SORT JOIN                   |                          |     4 |   140 |       |     8  (13)|
|  15 |             TABLE ACCESS BY INDEX ROWID| CONTAINER                |     4 |   140 |       |     7   (0)|
|* 16 |              INDEX RANGE SCAN          | CONTAINERBYLADATE        |     5 |       |       |     3   (0)|
|  17 |           BUFFER SORT                  |                          |    25 |   200 |       |     9  (23)|
|  18 |            TABLE ACCESS FULL           | PACKAGE                  |    25 |   200 |       |     3   (0)|
|  19 |          BUFFER SORT                   |                          |   552 |  6624 |       |    84   (3)|
|  20 |           TABLE ACCESS FULL            | RESOURCEDEF              |   552 |  6624 |       |     4   (0)|
|  21 |         BUFFER SORT                    |                          |  2020 | 24240 |       |   210K  (1)|
|  22 |          TABLE ACCESS FULL             | PRODUCTFAMILY            |  2020 | 24240 |       |    24   (0)|
|  23 |        BUFFER SORT                     |                          |  4814 | 81838 |       |   942M  (1)|
|  24 |         TABLE ACCESS FULL              | EMPLOYEE                 |  4814 | 81838 |       |    54   (2)|
|  25 |       BUFFER SORT                      |                          |   638 | 12122 |       |   521G  (1)|
|  26 |        TABLE ACCESS FULL               | OPERATION                |   638 | 12122 |       |     6   (0)|
|  27 |      BUFFER SORT                       |                          |   411K|  2009K|       |   204P  (1)|
|  28 |       TABLE ACCESS FULL                | SPLITHISTORYDETAILS      |   411K|  2009K|       |  3785   (1)|
|  29 |     BUFFER SORT                        |                          |  1171K|  5720K|       |    18E  (0)|
|  30 |      TABLE ACCESS FULL                 | QTYHISTORY               |  1171K|  5720K|       |  4690   (1)|
|  31 |    BUFFER SORT                         |                          |  1382 | 13820 |       |    18E  (0)|
|  32 |     TABLE ACCESS FULL                  | LOSSREASON               |  1382 | 13820 |       |     4   (0)|
----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

  13 - access("HML"."TXNDATE">=TO_DATE(' 2014-06-23 06:00:00', 'syyyy-mm-dd hh24:mi:ss') AND 
              "HML"."TXNDATE" IS NOT NULL)
  14 - access(TO_CHAR(INTERNAL_FUNCTION("HML"."TXNDATE"),'MM/DD/YYYY')<=TO_CHAR(INTERNAL_FUNCTION("CON".
              "LASTACTIVITYDATE"),'MM/DD/YYYY'))
       filter(TO_CHAR(INTERNAL_FUNCTION("HML"."TXNDATE"),'MM/DD/YYYY')<=TO_CHAR(INTERNAL_FUNCTION("CON".
              "LASTACTIVITYDATE"),'MM/DD/YYYY'))
  16 - access("CON"."LASTACTIVITYDATE">=TO_DATE(' 2014-06-23 06:00:00', 'syyyy-mm-dd hh24:mi:ss') AND 
              "CON"."LASTACTIVITYDATE"<TO_DATE(' 2014-06-24 06:00:00', 'syyyy-mm-dd hh24:mi:ss'))

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

enter code here

答案已经在评论中给出了:你正在交叉加入你的tables。

首先,您要获取 table Container 在特定日期范围内的所有记录。假设这是 200 条记录。然后你从 table package 中获取所有记录。假设此 table 包含 300 条记录。合并所有记录,得到 300 x 200 = 60000 条记录。然后你取下一个 table 并再次相乘,...

人们会期望 table 以某种方式相关,因此您会使用这些关系。假设每个包都位于一个容器中。因此,每个包裹记录都会有一个容器 ID。您不想将所有包连接到所有容器,而是将每个包连接到它所属的一个容器:

FROM container con 
JOIN package pack ON pack.container_id = con.id

也可以这样做

FROM container con, package pack 
WHERE pack.container_id = con.id

但你不应该。这种容易出错的隐式连接语法在二十多年前被上面提到的显式连接所取代。如果你用过

FROM container con 
JOIN package pack

如果没有 ON 子句,那么 DBMS 会注意到您的错误并告诉您正确连接记录而不是执行无意义的查询。


编辑:关于您在编辑中发布的原始查询,请确保 vw_power_overallyield_batchfe 视图中的所有 table 都正确连接并且您在链接列上有索引。那么你几乎无能为力。在日期列上建立索引可能会有所帮助,因为 DBMS 可能会决定使用范围索引扫描。您还可以尝试执行并行化查询(使用 PARRALLEL HINT)。

to_char(scraptxndate, 'MM/DD/YY') <= TXNDATEOUT 行看起来很可疑,顺便说一句。例如,'12/31/14' 将大于 '01/01/15'。这似乎没有意义。难道你不想比较日期,即 scraptxndate <= to_date(TXNDATEOUT,'MM/DD/YY')?