-3

表myfirst3有4列和120万条记录。Oracle 11g中的子句性能问题

表mtl_object_genealogy拥有超过1000万条记录。

运行下面的代码需要很长时间。如何使用选项调整此代码?

WITH level1 as ( 
    SELECT mln_parent.lot_number, 
      mln_parent.inventory_item_id, 
      gen.lot_num ,--fg_lot, 
      gen.segment1, 
      gen.rcv_date. 
    FROM mtl_lot_numbers mln_parent, 
      (SELECT MOG1.parent_object_id, 
        p.segment1, 
        p.lot_num, 
        p.rcv_date 
      FROM mtl_object_genealogy MOG1 , 
       myfirst3 p 
      START WITH MOG1.object_id = p.gen_object_id 
      AND (MOG1.end_date_active IS NULL OR MOG1.end_date_active > SYSDATE) 
      CONNECT BY nocycle PRIOR MOG1.parent_object_id = MOG1.object_id 
      AND (MOG1.end_date_active IS NULL OR MOG1.end_date_active > SYSDATE) 
      UNION all 
      SELECT p1.gen_object_id, 
        p1.segment1, 
        p1.lot_num, 
        p1.rcv_date 
      FROM myfirst3 p1) gen 
    WHERE mln_parent.gen_object_id = gen.parent_object_id) 
select /*+ NO_CPU_COSTING */ * 
from level1; 

执行计划

enter image description here

CREATE TABLE APPS.MYFIRST3 
(
    TO_ORGANIZATION_ID NUMBER, 
    LOT_NUM    VARCHAR2(80 BYTE), 
    ITEM_ID    NUMBER, 
    FROM_ORGANIZATION_ID NUMBER, 
    GEN_OBJECT_ID   NUMBER, 
    SEGMENT1    VARCHAR2(40 BYTE), 
    RCV_DATE    DATE 
); 

CREATE TABLE INV.MTL_OBJECT_GENEALOGY 
(
    OBJECT_ID    NUMBER    NOT NULL, 
    OBJECT_TYPE    NUMBER    NOT NULL, 
    PARENT_OBJECT_ID  NUMBER    NOT NULL, 
    START_DATE_ACTIVE  DATE     NOT NULL, 
    END_DATE_ACTIVE   DATE, 
    GENEALOGY_ORIGIN  NUMBER, 
    ORIGIN_TXN_ID   NUMBER, 
    GENEALOGY_TYPE   NUMBER, 
); 

CREATE INDEX INV.MTL_OBJECT_GENEALOGY_N1 ON INV.MTL_OBJECT_GENEALOGY(OBJECT_ID); 

CREATE INDEX INV.MTL_OBJECT_GENEALOGY_N2 ON INV.MTL_OBJECT_GENEALOGY(PARENT_OBJECT_ID); 
+2

哪里表定义?执行计划?请编辑您的问题并提供所有必要的信息。 – sagi

+0

请阅读http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-asking-a-question/285557和接受的答案 –

回答

0

你解释计划显示了一些非常大的数字。优化器认为最终结果集约为32,270,000,000,000行。只需返回多行就需要一些时间。

所有表访问都是全表扫描。因为你有大桌子,也会吃时间。

至于改进,我们很难理解查询的逻辑。这是你的数据模型,你的商业规则,你的数据。你没有解释任何事情,所以我们所能做的只是猜测。

你为什么使用WITH子句?您只使用level结果集一次,所以只需要一个常规的FROM子句。

你为什么使用UNION ALL?该操作只是复制从myfirst3检索的记录(所有这些值都已经列为行,其中MOG1.object_id = p.gen_object_id

合并连接CARTESIAN操作很有趣。Oracle使用它来实现传递闭包,这是一个昂贵的操作,但是这是因为树遍历一个层次结构是一件很昂贵的事情,很不幸,你正在为一个有2700万条记录的表生成所有的父子关系,这很糟糕。在myfirst3上没有过滤器,所以显然数据库必须得到所有记录。如果每个myfirst3记录有一个父记录,那么这个记录就是内容的10%mtl_object_genealogy,所以全表扫描将是有效的;但是你正在卷起整个层次结构,这就像你在查看更多的表格。

在面对这样的数字时,您的索引无关紧要。有什么可以帮助的是mtl_object_genealogy(OBJECT_ID, PARENT_OBJECT_ID, END_DATE_ACTIVE)上的综合指数。

您需要myfirst3中记录的PARENT_OBJECT_ID的所有级别。如果你经常运行这个查询,并且mtl_object_genealogy是一个缓慢变化的表格,你应该考虑把传递闭包变成一个表格,该表格只记录叶片记录和父母的所有排列。

综上所述:

  1. 沟WITH子句
  2. 降UNION ALL
  3. 调树散步的复合指数(或去实现它)