从plsql块执行查询需要太长时间

时间:2012-11-27 09:53:11

标签: oracle plsql

这个查询单独执行时需要1秒才能执行相同的查询通过程序执行它需要20秒,请帮我这个

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

2 个答案:

答案 0 :(得分: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>

如果这没有帮助,请查看您的解释计划(并在此处发布)。找出基数估计最错误的地方,然后试着找出原因。

答案 1 :(得分:-2)

您的查询太大,在批量数据上执行时会花费时间。尝试放置一些非规范化的临时表,在那里提取数据,然后在临时表之间进行连接。这将提高性能。

使用这个独立查询,不要在子查询中传递任何变量,如下面的行...

  

WHERE(wo.bb_ticker_id IN(选择
                             table_(v_tickerlist)

中的column_value

此外,外连接将抛出性能..更好地实现非规范化临时表