【问题标题】:Oracle Procedure Takes long time to run but the straight sql runs quickOracle过程运行时间长,但直接sql运行速度快
【发布时间】:2016-01-11 10:19:18
【问题描述】:

我有一个在程序之外运行非常流畅的 sql 块。在我将sql块放入过程中返回ref_cursor的那一刻,过程需要相当长的时间来执行ref_cursor。

在 DBA 的帮助下,我们实施了 DB 配置文件,它在加速过程方面效果很好,但随后对该特定过程的任何微小更改都会使其陷入混乱。我不确定是什么问题..我的选择已经不多了。我应该如何解决这个特别奇怪的问题?

提前谢谢你。

编辑..这里是查询

with query_ownership as (SELECT leeo.legal_entity_id,
                           leeo.parent_le_id,
                           SUM(leeo.effective_ownership) ownership_percent
                      FROM data_ownership leeo
                     WHERE leeo.start_date <=
                           to_date('12/31/2012','mm/dd/yyyy')
                       AND ((leeo.end_date < &lvTaxYearDate and leeo.end_date > &lvTaxYearBeginDate)
                           to_date('12/31/2012','mm/dd/yyyy') OR
                           leeo.end_date IS NULL)
                       and leeo.stock_type in ('E')
                     GROUP BY leeo.legal_entity_id, leeo.parent_le_id
                    HAVING SUM(leeo.effective_ownership) > 0
),
query_branches as ( SELECT b.branch_id       as legal_entity_id,
                           b.legal_entity_id as perent_le_id,
                           1.00              as ownership_percent
                      FROM company_branches b
                     WHERE b.tax_year = 2012),
child_query as (select * from query_ownership
                    UNION
           select * from query_branches),
parent_query as (select * from query_ownership
                    UNION
           select * from query_branches),                                       
inner_query as (SELECT rownum                        as sortcode,
                   -level                        as lvl,
                   child_query.parent_le_id,
                   child_query.legal_entity_id,
                   child_query.ownership_percent
              FROM child_query
             START WITH child_query.legal_entity_id = 'AB1203'
            CONNECT BY NOCYCLE PRIOR child_query.legal_entity_id =
                        child_query.parent_le_id
                   AND child_query.ownership_percent >= 0.01
                   and level = 0
            UNION
            SELECT rownum as sortcode,
                   level - 1 as lvl,
                   parent_query.parent_le_id,
                   parent_query.legal_entity_id,
                   parent_query.ownership_percent
              FROM parent_query
             START WITH parent_query.legal_entity_id = 'AB1203'
            CONNECT BY NOCYCLE
             PRIOR parent_query.parent_le_id =
                        parent_query.legal_entity_id
                   AND parent_query.ownership_percent >= 0.01)
                  ,ownership_heirarchy as (
               SELECT max(inner_query.sortcode) as sortcode,
           max(inner_query.lvl) as lvl,
           inner_query.parent_le_id,
           inner_query.legal_entity_id,
           inner_query.ownership_percent from inner_query
     GROUP BY inner_query.parent_le_id,
              inner_query.legal_entity_id,
              inner_query.ownership_percent
              )
              ,goldList as (
SELECT lem2.legal_entity_id from ownership_heirarchy,
   company_entity_year lem1,
   company_entity_year lem2
WHERE ownership_heirarchy.parent_le_id = lem2.legal_entity_id
AND lem2.tax_year = 2012

AND ownership_heirarchy.legal_entity_id = lem1.legal_entity_id
AND lem1.tax_year = 2012
AND lem1.legal_entity_type <> 'EXT'
AND lem1.non_legal_entity_flag is null
AND lem2.legal_entity_type <> 'EXT'
AND lem2.non_legal_entity_flag is null
and TRIM(lem2.alt_tax_type) is null
and UPPER(lem2.tax_type) in ('DC', 'DPS', 'TXN')
),
fulllist as (
         select * from goldList
        union
         select gc.parent_le_id from company_entity_year e,       consolidation_group gc 
where e.LEGAL_ENTITY_ID = 'AB1203' and e.tax_year = 2012
and e.TAX_CONSOLIDATION_GRP = gc.group_id
        union
         select e.leid from vdst_entity e where e.TAX_YEAR = 2012
         and e.ALT_TAX_TYPE in (3,8)
         and e.LEID = 'AB1203'
) 

  select  distinct dc.dcn_id      as dcnId,
         dc.dcn_name    as dcnName,
         dy.dcn_year_id dcnYearId,
         ty.tax_year_id taxYearId,
         ty.tax_year    taxYear
    from company_dcn dc, company_dcn_year dy, company_tax_year ty
   where dc.dcn_id = dy.dcn_id
     and dy.year_id = ty.tax_year_id
     and ty.tax_year = 2012
     and dc.leid in (
         select * from fulllist
                     ); 

【问题讨论】:

  • 问题显然出在存储过程的第 17 行。
  • 更新了问题以包含有问题的查询。
  • 听起来对于带有文字(“在过程之外平滑”)和绑定变量(在 PL/SQL 中)的查询可能有不同的执行计划。
  • 更新:我最终为我在程序中使用的一些 mat 视图创建了索引,并且性能相当不错。谢谢大家的帮助。

标签: oracle performance stored-procedures oracle11g


【解决方案1】:

找出执行计划的哪一部分导致了问题。有几种方法可以做到这一点:

  1. 使用DBMS_XPLAN 找出好的和坏的计划。 使用explain plan for ...select * from table(dbms_xplan.display); 在你的课程中找出好的计划。使用dbms_xplan.display_cursor(sql_id =&gt; 'some sql_id') 查找错误计划。比较计划并寻找差异。这可能非常困难,因为您通常无法判断执行计划的哪些部分很慢。如果幸运的话,只会有一个差异,那么显然这个差异就是问题所在。
  2. 使用DBMS_SQLTUNE.REPORT_SQL_MONITOR 找出执行计划的哪一部分是错误的。 运行错误查询并使用 SQL 监控找出执行计划中的哪个操作错误。该报告显示了哪些操作耗时最长,哪些基数估计偏差最大。专注于缓慢的部分,以及计划的第一步,估计与实际之间存在巨大的基数差异。
  3. 查看配置文件提示以了解 Oracle 如何修复错误计划。配置文件是帮助优化器做出正确决策的提示集合。这些提示可能会告诉您问题所在。例如,如果提示之一是OPT_ESTIMATE(JOIN (A B) SCALE_ROWS=100),则配置文件告诉优化器将基数估计增加 100 倍。您可以通过在查询中包含该提示或通过创建和锁定假表统计信息来重新创建相同的影响。使用来自 Kerry Osborne 的 this process 查找个人资料提示。

无论哪种方式,此过程都可能既困难又耗时。尽量缩小查询。有时调整 97 行查询几乎是不可能的。可能只有一个根本问题,但这个问题对执行计划的影响很大,看起来好像有十几个问题。

这些步骤仅帮助您识别问题。修复它可能是另一个问题和答案。

【讨论】:

    【解决方案2】:

    首先,通过为查询中涉及的每个表运行DBMS_STATS.GATHER_TABLE_STATS,确保统计信息是最新的。接下来,获取具有不同参数值的查询计划——参数的变化完全有可能使计划变得更好或更糟。鉴于您没有向我们展示有关查询、过程和所涉及的表的信息,因此无法更具体。

    祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      • 2016-06-25
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      相关资源
      最近更新 更多