2012-11-27 99 views
2

這個查詢執行的,請幫我在這查詢時間太長,從PLSQL塊

SELECT * FROM 
    (SELECT TAB1.*,ROWNUM ROWNUMM FROM 
     (SELECT wh.workitem_id, wh.workitem_priority, wh.workitem_type_id, wt.workitem_type_nm, 
      wh.workitem_status_id, ws.workitem_status_nm, wh.analyst_group_id, 
      ag.analyst_group_nm, wh.owner_uuid, earnings_estimate.pr_get_name_from_uuid(owner_uuid) owner_name, 
      wh.create_user_id, earnings_estimate.pr_get_name_from_uuid(wh.create_user_id) create_name, wh.create_ts, 
      wh.update_user_id,earnings_estimate.pr_get_name_from_uuid(wh.update_user_id) update_name, wh.update_ts, wh.bb_ticker_id, wh.node_id, 
      wh.eqcv_analyst_uuid, earnings_estimate.pr_get_name_from_uuid(wh.eqcv_analyst_uuid) eqcv_analyst_name, 
      WH.WORKITEM_NOTE,Wh.PACKAGE_ID ,Wh.COVERAGE_STATUS_NUM ,CS.COVERAGE_STATUS_CD ,Wh.COVERAGE_REC_NUM,I.INDUSTRY_CD INDUSTRY_CODE,I.INDUSTRY_NM 
INDUSTRY_NAME,WOT.WORKITEM_OUTLIER_TYPE_NM as WORKITEM_SUBTYPE_NM 
      ,count(1) over() AS total_count,bro.BB_ID BROKER_BB_ID,bro.BROKER_NM BROKER_NAME, wh.assigned_analyst_uuid,earnings_estimate.pr_get_name_from_uuid(wh.assigned_analyst_uuid) 
assigned_analyst_name 
    FROM earnings_estimate.workitem_type wt, 
      earnings_estimate.workitem_status ws, 
      earnings_estimate.workitem_outlier_type wot, 
      (SELECT * FROM (
       SELECT WH.ASSIGNED_ANALYST_UUID,WH.DEFERRED_TO_DT,WH.WORKITEM_NOTE,WH.UPDATE_USER_ID,EARNINGS_ESTIMATE.PR_GET_NAME_FROM_UUID(WH.UPDATE_USER_ID) 
UPDATE_NAME, WH.UPDATE_TS,WH.OWNER_UUID, EARNINGS_ESTIMATE.PR_GET_NAME_FROM_UUID(OWNER_UUID) 
OWNER_NAME,WH.ANALYST_GROUP_ID,WH.WORKITEM_STATUS_ID,WH.WORKITEM_PRIORITY,EARNINGS_ESTIMATE.PR_GET_NAME_FROM_UUID(WI.CREATE_USER_ID) CREATE_NAME, WI.CREATE_TS, 
       wi.create_user_id,wi.workitem_type_id,wi.workitem_id,RANK() OVER (PARTITION BY WH.WORKITEM_ID ORDER BY WH.CREATE_TS DESC NULLS LAST, ROWNUM) R, 
       wo.bb_ticker_id, wo.node_id,wo.eqcv_analyst_uuid, 
       WO.PACKAGE_ID ,WO.COVERAGE_STATUS_NUM ,WO.COVERAGE_REC_NUM, 
       wo.workitem_outlier_type_id        
        FROM earnings_estimate.workitem_history wh 
        JOIN EARNINGS_ESTIMATE.workitem_outlier wo 
        ON wh.workitem_id=wo.workitem_id 
        JOIN earnings_estimate.workitem wi 
        ON wi.workitem_id=wo.workitem_id 
        AND WI.WORKITEM_TYPE_ID=3 
        and wh.workitem_status_id not in (1,7) 
        WHERE (wo.bb_ticker_id IN (SELECT 
          column_value from table(v_tickerlist) ) 
      ) 
    )wh 
         where r=1 
        AND DECODE(V_DATE_TYPE,'CreatedDate',WH.CREATE_TS,'LastModifiedDate',WH.UPDATE_TS) >= V_START_DATE 
        AND decode(v_date_type,'CreatedDate',wh.create_ts,'LastModifiedDate',wh.update_ts) <= v_end_date 
        and decode(wh.owner_uuid,null,-1,wh.owner_uuid)=decode(v_analyst_id,null,decode(wh.owner_uuid,null,-1,wh.owner_uuid),v_analyst_id) 
        ) wh, 
      earnings_estimate.analyst_group ag, 
      earnings_estimate.coverage_status cs, 
      earnings_estimate.research_document rd, 
     (SELECT 
      BB.BB_ID , 
       BRK.BROKER_ID, 
       BRK.BROKER_NM 
      FROM EARNINGS_ESTIMATE.BROKER BRK,COMMON.BB_ID BB 
      WHERE BRK.ORG_ID = BB.ORG_ID 
      AND BRK.ORG_LOC_REC_NUM = BB.ORG_LOC_REC_NUM 
      AND BRK.primary_broker_ind='Y') bro, 
      earnings_estimate.industry i 
    WHERE wh.analyst_group_id = ag.analyst_group_id 
     AND wh.workitem_status_id = ws.workitem_status_id 
     AND wh.workitem_type_id = wt.workitem_type_id 
     AND wh.coverage_status_num=cs.coverage_status_num 
     AND wh.workitem_outlier_type_id=wot.workitem_outlier_type_id 
     AND wh.PACKAGE_ID=rd.PACKAGE_ID(+) 
     AND rd.industry_id=i.industry_id(+) 
     AND rd.BROKER_BB_ID=bro.BB_ID(+) 
     ORDER BY wh.create_ts)tab1) 
     ; 
+0

1)避免使用舊式聯接(它們通常效率較低**和**不是每個人都知道並理解它們) 2)簡化查詢 - 它太大而無法閱讀,在簡化過程中可能會出現找到你的問題。 3)子選擇是**從不**有良好的表現 –

+1

當你說獨自執行,你是什麼意思?在一個GUI或sqlplus?同樣,如果你在GUI上運行它,你是否滾動到最後一行,而不是隻看到結果的1個「頁面」返回的時間?在sqlplus'set autotrace traceonly'中執行此操作' '設置時間安排' '(運行您的選擇)' 並將輸出粘貼到您的問題中。 – DazzaL

+0

在sqlplus中執行它只有兩行作爲結果 – Bhagwat

回答

-2

你查詢太大,在批量數據上執行時需要時間。嘗試使用很少的非標準化臨時表,在那裏提取數據,然後在臨時表之間進行連接。這會提高性能。

有了這個獨立的查詢,不傳子查詢內的任何變量,在下面的行...

WHERE(wo.bb_ticker_id IN(SELECT從表
COLUMN_VALUE(v_tickerlist)

此外,外連接會折騰的性能..更好地落實去歸一化臨時表

+1

查詢文本的大小對性能沒有影響。就個人而言,我認爲用臨時表來優化一個特定的查詢並不是一個好方法。 – eaolson

0

我同意,問題最有可能涉及到SELECT column_value from table(v_tickerlist)

默認情況下,Oracle估計表函數返回8168行。由於您使用單個值來測試查詢,因此我認爲實際值的數量通常要小得多。像任何預測一樣,基數估計總是錯誤的。但是他們至少應該處於實際基數的大部分範圍內,以便優化器正確地完成其工作。

您可以強制Oracle始終使用動態採樣檢查大小。這將需要更多時間來生成計劃,但在這種情況下它可能是值得的。

例如:

SQL> --Sample type 
SQL> create or replace type v_tickerlist is table of number; 
    2/

Type created. 

SQL> --Show explain plans 
SQL> set autotrace traceonly explain; 
SQL> --Default estimate is poor. 8168 estimated, versus 3 actual. 
SQL> SELECT column_value from table(v_tickerlist(1,2,3)); 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1748000095 

---------------------------------------------------------------------------------------------- 
| Id | Operation        | Name | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT      |  | 8168 | 16336 | 16 (0)| 00:00:01 | 
| 1 | COLLECTION ITERATOR CONSTRUCTOR FETCH|  | 8168 | 16336 | 16 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------- 

SQL> --Estimate is perfect when dynamic sampling is used. 
SQL> SELECT /*+ dynamic_sampling(tickerlist, 2) */ column_value 
    2 from table(v_tickerlist(1,2,3)) tickerlist; 

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1748000095 

---------------------------------------------------------------------------------------------- 
| Id | Operation        | Name | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT      |  |  3 |  6 |  6 (0)| 00:00:01 | 
| 1 | COLLECTION ITERATOR CONSTRUCTOR FETCH|  |  3 |  6 |  6 (0)| 00:00:01 | 
---------------------------------------------------------------------------------------------- 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 

SQL> 

如果沒有幫助,看看你的解釋計劃(和張貼在這裏)。找出基數估計最錯誤的地方,然後嘗試找出原因。