2016-05-30 398 views
0

我有一個問題,如何在一個存儲過程的執行計劃創建,如果它有一個IF ELSE語句,其中IF或執行ELSE塊上的IN參數的值基於並且塊中的查詢從相同的表中獲取相同的值,但在where子句中具有不同的列。Oracle存儲過程的執行計劃

據我所知,每個存儲過程只有一個執行計劃。如果Java應用程序使用普通JDBC調用存儲過程,則在第一次調用該過程時創建執行計劃,並使用塊(IF)執行以創建執行計劃。

當執行ELSE塊,它使用相同的執行計劃並且因此執行將是緩慢的下一次。

我問這個問題,因爲我呼籲類似的存儲過程和執行的時間是執行基於什麼樣的價值我傳遞和塊很大的不同。

如果是這種情況,可以採取哪些措施來提高性能。應該寫一個獨立的程序而不是使用IF ELSE。

PFB存儲的過程代碼:

PACKAGE   COP00134_006_1 AS 
    TYPE t_cur_type IS REF CURSOR; 
    PROCEDURE GetConsignmentDetails(
     sPInputList  IN VARCHAR2, 
     sPInputType  IN VARCHAR2, 
     cPCon   OUT t_cur_type, 
     cPStatus  OUT t_cur_type, 
     sPError   OUT VARCHAR2); 
END COP00134_006_1; 

實現:

PACKAGE BODY   COP00134_006_1 AS 
    PROCEDURE GetConsignmentDetails(
     sPInputList  IN VARCHAR2, 
     sPInputType  IN VARCHAR2, 
     cPCon   OUT t_cur_type, 
     cPStatus  OUT t_cur_type, 
     sPError   OUT VARCHAR2) 
    IS 
    BEGIN 
     sPError := '0'; 
     IF sPInputType = 'CON' THEN 
     OPEN cPCon FOR 
      SELECT 
        con_id 
        ,con_legacy_id 
        ,con_create_td 
        ,con_pickup_lt 
        ,con_deliv_due_lt 
        ,CON_DELIV_END_LT 
        ,SRP_ID_AREA_DEST 
        ,CON_CLNT_REF_TX 
        ,BUL_CSYS_ID_ORIG 
        ,BUL_ID_ORIG 
        ,BUL_NM_ORIG 
        ,BUL_NM_DEST 
        ,cpn_oa_town_nm_r 
        ,cpn_oa_town_nm_d 
        ,cou_iso_id_orig 
        ,Cou_Nm_Orig 
        ,cou_iso_id_dest 
        ,Cou_Nm_Dest 
        ,PCE_QT 
        ,DUPLICATES 
        ,COS_SIGN_NM FROM (
      SELECT /*+ cardinality (b 3) */ 
        co.con_id 
        ,co.con_legacy_id 
        ,co.con_create_td 
        ,co.con_pickup_lt 
        ,co.con_deliv_due_lt 
        ,co.CON_DELIV_END_LT 
        ,co.SRP_ID_AREA_DEST 
        ,co.CON_CLNT_REF_TX 
        ,co.BUL_CSYS_ID_ORIG 
        ,blOrig.BUL_ID as BUL_ID_ORIG 
        ,blOrig.BUL_NM as BUL_NM_ORIG 
        ,blDest.BUL_NM as BUL_NM_DEST 
        ,cnr.cpn_oa_town_nm as cpn_oa_town_nm_r 
        ,cnd.cpn_oa_town_nm as cpn_oa_town_nm_d 
        ,co.cou_iso_id_orig 
        ,cuOrig.Cou_nm as Cou_Nm_Orig 
        ,co.cou_iso_id_dest 
        ,cuDest.Cou_nm as Cou_Nm_Dest 
        ,(select count(*) from CORPCV01 PC WHERE PC.CON_ID = CO.CON_ID) PCE_QT 
        ,CASE WHEN COUNT(*) OVER(PARTITION BY CON_LEGACY_ID) > 1 THEN 'TRUE' ELSE 'FALSE' END AS DUPLICATES 
        ,cs.COS_SIGN_NM, ROW_NUMBER() OVER(PARTITION BY CS.CON_ID ORDER BY COS_EVENT_TD) SEQ_NR 
       FROM corcov01 co 
       INNER JOIN corcnv01 cnr 
       ON cnr.con_id = co.con_id 
       AND cnr.cpn_type_cd = 'R' 
       LEFT OUTER JOIN corcnv01 cnd 
       ON cnd.con_id = co.con_id 
       AND cnd.cpn_type_cd = 'D' 
       INNER JOIN ncrcuv01 cuOrig 
       ON cuOrig.COU_ISO_ID = co.COU_ISO_ID_ORIG 
       AND TRUNC(CURRENT_DATE) BETWEEN cuOrig.COU_EFFECT_DT AND cuOrig.COU_EFFECT_TO_DT 
       INNER JOIN ncrcuv01 cuDest 
       ON cuDest.COU_ISO_ID = co.COU_ISO_ID_DEST 
       AND TRUNC(CURRENT_DATE) BETWEEN cuDest.COU_EFFECT_DT AND cuDest.COU_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrblv01 blOrig 
       ON blOrig.BUL_CSYS_ID = co.BUL_CSYS_ID_ORIG 
       AND TRUNC(CURRENT_DATE) BETWEEN blOrig.BUL_EFFECT_DT AND blOrig.BUL_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrblv01 blDest 
       ON blDest.BUL_CSYS_ID = co.BUL_CSYS_ID_DEST 
       AND TRUNC(CURRENT_DATE) BETWEEN blDest.BUL_EFFECT_DT AND blDest.BUL_EFFECT_TO_DT 
       LEFT OUTER JOIN corcsv01 cs 
       ON co.con_id = cs.con_id 
       AND cs.cos_sign_nm is not null 
       and cs.cos_delete_in = 'N' 
       WHERE co.con_Legacy_Id IN (select dataItem from TABLE(ZYADMIN.ZYP90008.GetListFromCSV(sPInputList)) b) 
       )WHERE SEQ_NR = 1; 
      OPEN cPStatus FOR 
       SELECT csv.CON_ID AS CON_ID_COS 
        ,csv.XSF_ID 
        ,csv.XSS_ID 
        ,csv.XSG_ID 
        ,csv.XSD_ID 
        ,ndv.XSX_ID 
        ,ndv.xsd_customer_ds 
        ,BUL_CSYS_ID_OCC 
        ,nlv.BUL_NM as BUL_NM_OCC 
        ,csv.COS_EVENT_LT 
        ,ndv.XSD_SEVERITY_CD 
        ,qb.QLA_DS 
       FROM corcsv01 csv 
       INNER JOIN corcov01 co 
        ON csv.con_id = co.con_id 
       INNER JOIN ncrsdv01 ndv 
        ON ndv.XSF_ID=csv.XSF_ID 
       AND ndv.XSS_ID=csv.XSS_ID 
       AND ndv.XSG_ID=csv.XSG_ID 
       AND ndv.XSD_ID=csv.XSD_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN ndv.XSD_EFFECT_DT AND ndv.XSD_EFFECT_TO_DT 
       INNER JOIN ncrksv01 ks 
        ON ndv.XSX_ID= ks.XSX_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN ks.SKT_EFFECT_DT AND ks.SKT_EFFECT_TO_DT 
       AND ks.SCA_ID = 'WEB' 
       LEFT OUTER JOIN ncrqav01 qa 
       ON qa.XSX_ID = ndv.XSX_ID 
       AND qa.APP_ID = 'EXCO' 
       AND TRUNC(CURRENT_DATE) BETWEEN QAS_EFFECT_DT AND QAS_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrqbv01 qb 
       ON qa.QLA_ID = qb.QLA_ID 
       AND qa.APP_ID = qb.APP_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN QLA_EFFECT_DT AND QLA_EFFECT_TO_DT 
       INNER JOIN ncrblv01 nlv 
        ON nlv.BUL_CSYS_ID=csv.BUL_CSYS_ID_OCC 
       AND TRUNC(CURRENT_DATE)BETWEEN nlv.BUL_EFFECT_DT AND nlv.BUL_EFFECT_TO_DT 
       WHERE co.con_Legacy_Id IN (select dataItem from TABLE(ZYADMIN.ZYP90008.GetListFromCSV(sPInputList)) b); 
     ELSE 
     OPEN cPCon FOR 
        SELECT 
        con_id 
        ,con_legacy_id 
        ,con_create_td 
        ,con_pickup_lt 
        ,con_deliv_due_lt 
        ,CON_DELIV_END_LT 
        ,SRP_ID_AREA_DEST 
        ,CON_CLNT_REF_TX 
        ,BUL_CSYS_ID_ORIG 
        ,BUL_ID_ORIG 
        ,BUL_NM_ORIG 
        ,BUL_NM_DEST 
        ,cpn_oa_town_nm_r 
        ,cpn_oa_town_nm_d 
        ,cou_iso_id_orig 
        ,Cou_Nm_Orig 
        ,cou_iso_id_dest 
        ,Cou_Nm_Dest 
        ,PCE_QT 
        ,DUPLICATES 
        ,COS_SIGN_NM FROM (
      SELECT /*+ cardinality (b 3) */ 
        co.con_id 
        ,co.con_legacy_id 
        ,co.con_create_td 
        ,co.con_pickup_lt 
        ,co.con_deliv_due_lt 
        ,co.CON_DELIV_END_LT 
        ,co.SRP_ID_AREA_DEST 
        ,co.CON_CLNT_REF_TX 
        ,co.BUL_CSYS_ID_ORIG 
        ,blOrig.BUL_ID as BUL_ID_ORIG 
        ,blOrig.BUL_NM as BUL_NM_ORIG 
        ,blDest.BUL_NM as BUL_NM_DEST 
        ,cnr.cpn_oa_town_nm as cpn_oa_town_nm_r 
        ,cnd.cpn_oa_town_nm as cpn_oa_town_nm_d 
        ,co.cou_iso_id_orig 
        ,cuOrig.Cou_nm as Cou_Nm_Orig 
        ,co.cou_iso_id_dest 
        ,cuDest.Cou_nm as Cou_Nm_Dest 
        ,(select count(*) from CORPCV01 PC WHERE PC.CON_ID = CO.CON_ID) PCE_QT 
        ,'FALSE' AS DUPLICATES 
        ,cs.COS_SIGN_NM, ROW_NUMBER() OVER(PARTITION BY CS.CON_ID ORDER BY COS_EVENT_TD) SEQ_NR 
       FROM corcov01 co 
       INNER JOIN corcnv01 cnr 
       ON cnr.con_id = co.con_id 
       AND cnr.cpn_type_cd = 'R' 
       LEFT OUTER JOIN corcnv01 cnd 
       ON cnd.con_id = co.con_id 
       AND cnd.cpn_type_cd = 'D' 
       INNER JOIN ncrcuv01 cuOrig 
       ON cuOrig.COU_ISO_ID = co.COU_ISO_ID_ORIG 
       AND TRUNC(CURRENT_DATE) BETWEEN cuOrig.COU_EFFECT_DT AND cuOrig.COU_EFFECT_TO_DT 
       INNER JOIN ncrcuv01 cuDest 
       ON cuDest.COU_ISO_ID = co.COU_ISO_ID_DEST 
       AND TRUNC(CURRENT_DATE) BETWEEN cuDest.COU_EFFECT_DT AND cuDest.COU_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrblv01 blOrig 
       ON blOrig.BUL_CSYS_ID = co.BUL_CSYS_ID_ORIG 
       AND TRUNC(CURRENT_DATE) BETWEEN blOrig.BUL_EFFECT_DT AND blOrig.BUL_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrblv01 blDest 
       ON blDest.BUL_CSYS_ID = co.BUL_CSYS_ID_DEST 
       AND TRUNC(CURRENT_DATE) BETWEEN blDest.BUL_EFFECT_DT AND blDest.BUL_EFFECT_TO_DT 
       LEFT OUTER JOIN corcsv01 cs 
       ON co.con_id = cs.con_id 
       AND cs.cos_sign_nm is not null 
       and cs.cos_delete_in = 'N' 
       WHERE co.CON_CLNT_REF_CR IN (select dataItem from TABLE(ZYADMIN.ZYP90008.GetListFromCSV(sPInputList)) b) 
       )WHERE SEQ_NR = 1; 
      OPEN cPStatus FOR 
       SELECT csv.CON_ID AS CON_ID_COS 
        ,csv.XSF_ID 
        ,csv.XSS_ID 
        ,csv.XSG_ID 
        ,csv.XSD_ID 
        ,ndv.XSX_ID 
        ,ndv.xsd_customer_ds 
        ,BUL_CSYS_ID_OCC 
        ,nlv.BUL_NM as BUL_NM_OCC 
        ,csv.COS_EVENT_LT 
        ,ndv.XSD_SEVERITY_CD 
        ,qb.QLA_DS 
       FROM corcsv01 csv 
       INNER JOIN corcov01 co 
        ON csv.con_id = co.con_id 
       INNER JOIN ncrsdv01 ndv 
        ON ndv.XSF_ID=csv.XSF_ID 
       AND ndv.XSS_ID=csv.XSS_ID 
       AND ndv.XSG_ID=csv.XSG_ID 
       AND ndv.XSD_ID=csv.XSD_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN ndv.XSD_EFFECT_DT AND ndv.XSD_EFFECT_TO_DT 
       INNER JOIN ncrksv01 ks 
        ON ndv.XSX_ID= ks.XSX_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN ks.SKT_EFFECT_DT AND ks.SKT_EFFECT_TO_DT 
       AND ks.SCA_ID = 'WEB' 
       LEFT OUTER JOIN ncrqav01 qa 
       ON qa.XSX_ID = ndv.XSX_ID 
       AND qa.APP_ID = 'EXCO' 
       AND TRUNC(CURRENT_DATE) BETWEEN QAS_EFFECT_DT AND QAS_EFFECT_TO_DT 
       LEFT OUTER JOIN ncrqbv01 qb 
       ON qa.QLA_ID = qb.QLA_ID 
       AND qa.APP_ID = qb.APP_ID 
       AND TRUNC(CURRENT_DATE) BETWEEN QLA_EFFECT_DT AND QLA_EFFECT_TO_DT 
       INNER JOIN ncrblv01 nlv 
        ON nlv.BUL_CSYS_ID=csv.BUL_CSYS_ID_OCC 
       AND TRUNC(CURRENT_DATE)BETWEEN nlv.BUL_EFFECT_DT AND nlv.BUL_EFFECT_TO_DT 
       WHERE co.CON_CLNT_REF_CR IN (select dataItem from TABLE(ZYADMIN.ZYP90008.GetListFromCSV(sPInputList)) b); 
     END IF; 
    EXCEPTION 
     WHEN OTHERS THEN 
      sPError := '1' ||' '||SQLCODE||' '||SUBSTR(SQLERRM, 1, 200); 
    END; 
END COP00134_006_1; 

問題是在ELSE部分執行的查詢。 正如評論中所述,我單獨運行了相同的查詢,並且在不到一秒的時間內執行了相同的查詢,而當相同的數據傳遞到過程時,它需要一分多鐘。我不能運行探查,因爲我沒有訪問數據庫,並要求DBA爲同樣會採取一個多星期的過程中,我需要儘快

+0

AFAI,是的,如果您在通過jdbc從數據庫檢索數據時遇到性能問題,應該這樣做。 –

+2

SQL查詢具有執行計劃,而不是存儲過程(或針對該問題的任何PL/SQL代碼塊)。所以執行計劃將被視爲您的存儲過程中的每個查詢。你不會像你描述的那樣經歷這個問題。 – sstan

+0

@cihanseven - 不確定你的意思。如果已經正確配置,JDBC能夠提供良好的性能。 – APC

回答

0

甲骨文建立執行計劃的查詢不存儲過程解決這個問題。因此,存儲過程中的每個查詢都將擁有自己的執行計劃。你說這約yoour查詢:

「在where子句不同的列」

不同的列是指不同的訪問路徑:這可能轉化爲不同的使用指標,不同的磁盤讀取活動,可能不同的數據量。因此,取決於IF ... ELSE的哪個分支,體驗不同的性能並不令人驚訝。分開的過程不會改變底層查詢的性能。

要檢查差異,請爲每個單獨的查詢運行EXPLAIN PLAN。 Find out more。您需要將這些語句刪除到SQL工作表(或者用於SQL的任何工具)中。


如果您認爲問題出在存儲過程,那麼您應該調查PL/SQL分析器所處的時間。 Find out more。如果它尚未安裝,則可能需要安裝DBA才能安裝它。


「時相同的查詢執行內部存儲過程具有相同的價值觀和相同的數據正在採取60+秒」

你一直談論經過的時間。你如何衡量這些?你在測量什麼?時間到了哪裏?當實際的罪魁禍首是一個糟糕的JDBC配置的錯誤網絡連接時,這不會是數據庫首次因性能較差而受到指責。

+0

我已經運行解釋計劃的個人查詢和解釋計劃看起來不錯。此外,查詢在不到0.5秒的時間內執行完畢。但是,當相同的查詢在存儲過程中執行相同的值和相同的數據時,需要60+秒。 – Neel

+0

我們已經達到了StackOverflow上的人們可以使用迄今爲止提供的信息的限制。診斷需要線索:它需要查看代碼,原始數據,樣本輸入和輸出,解釋計劃和配置文件。 – APC

+0

我已經添加了存儲過程代碼。希望我能得到一些東西。 – Neel

相關問題