簡體   English   中英

Oracle 11g 中的 WITH 子句性能問題

[英]WITH Clause performance issue in Oracle 11g

表 myfirst3 有 4 列和 120 萬條記錄。

表 mtl_object_genealogy 有超過 1000 萬條記錄。

運行下面的代碼需要很長時間。 如何使用 with 選項調整此代碼?

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

你的解釋計划顯示了一些非常大的數字。 優化器估計最終結果集將約為 3227,000,000,000 行。 僅僅返回那么多行需要一些時間。

所有表訪問都是全表掃描。 因為你有大桌子,也會吃時間。

至於改進,我們很難理解您的查詢邏輯。 這是您的數據模型、您的業務規則、您的數據。 你沒有解釋任何事情,所以我們只能猜測。

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

為什么要使用 UNION ALL? 該操作只是復制從myfirst3檢索到的記錄(所有這些值都已包含在MOG1.object_id = p.gen_object_id行中。

MERGE JOIN CARTESIAN 操作很有趣。 Oracle 使用它來實現傳遞閉包。 這是一個昂貴的操作,但那是因為樹遍歷層次結構是一件昂貴的事情。 不幸的是,您正在為具有 2700 萬條記錄的表生成所有父子關系。 那很糟。

全表掃描不是問題。 myfirst3上沒有過濾器,因此顯然數據庫必須獲取所有記錄。 如果每個myfirst3記錄有一個父項,它是內容mtl_object_genealogy的 10%,那么全表掃描將是有效的; 但是您正在卷起整個層次結構,因此就像您正在查看表格的更大部分一樣。

面對這些數字,您的索引無關緊要。 可能有幫助的是mtl_object_genealogy(OBJECT_ID, PARENT_OBJECT_ID, END_DATE_ACTIVE)上的復合索引。

您需要myfirst3記錄的所有級別的 PARENT_OBJECT_ID 。 如果你經常運行這個查詢並且mtl_object_genealogy是一個緩慢變化的表,你應該考慮將傳遞閉包物化到一個表中,該表只包含葉記錄和父項的所有排列的記錄。

總結:

  1. 拋棄 WITH 子句
  2. 刪除 UNION ALL
  3. 使用復合索引(或實現它)調整樹遍歷

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM