【问题标题】:WITH Clause performance issue in Oracle 11gOracle 11g 中的 WITH 子句性能问题
【发布时间】:2018-03-26 23:42:07
【问题描述】:

表 myfirst3 有 4 列和 120 万条记录。

表 mtl_object_genealogy 有超过 1000 万条记录。

运行以下代码需要很长时间。如何使用 with options 调整此代码?

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;

执行计划

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);

【问题讨论】:

标签: oracle performance oracle11g query-optimization database-performance


【解决方案1】:

您的解释计划显示了一些非常大的数字。优化器估计最终结果集将是大约 3227,000,000,000 行。仅仅返回这么多行需要一些时间。

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

至于改进,我们很难理解您查询的逻辑。这是您的数据模型、业务规则和数据。你什么都没有解释,所以我们只能猜测。

为什么要使用 WITH 子句?您只使用一次level 结果集,因此只需使用常规的 FROM 子句即可。

为什么要使用 UNION ALL?该操作只是复制从myfirst3 检索到的记录(所有这些值都已包含在MOG1.object_id = p.gen_object_id 所在的行中。

MERGE JOIN 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. 使用复合索引(或将其具体化)调整 tree-walk

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-14
    • 2015-07-30
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多