-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. 調樹散步的複合指數(或去實現它)