【问题标题】:Queries on user_cons_columns much slower in Oracle 12c在 Oracle 12c 中对 user_cons_columns 的查询要慢得多
【发布时间】:2017-11-02 20:30:44
【问题描述】:

我们正在从 Oracle 11g 升级到 12c,并注意到对 user_cons_columns 的查询似乎要慢一些。

例如,即使在较小的数据集上,速度也会慢 4 倍:

select uc.search_condition 
from user_constraints uc inner join user_cons_columns ucc on ucc.CONSTRAINT_NAME = uc.CONSTRAINT_NAME  
where ucc.table_name = :upper_table_name
and ucc.column_name = :upper_column

这只是收集统计数据的问题吗?

【问题讨论】:

  • 但是您在哪里检查这些值?你已经升级了吗?就地升级后,您可能会遇到一些性能下降。 Ps:你只有那个你注意到很慢的查询?对其他表的所有其他查询都相同吗?
  • 这是在一个干净的测试 12c 系统上,我们已经完成了我们的应用程序的干净安装,所以不是升级。其他查询似乎没有这个问题。
  • 我确信 Oracle 强烈建议不要在数据字典表上收集统计信息,因此我会在执行此操作之前进行检查。解决问题的最佳起点是解释计划并与之前的版本进行比较。
  • @TenG - 这在很久以前可能是正确的,但自从 11G(如果不是更早)Oracle 建议我们可以对数据字典进行统计。这就是为什么 DBMS_STATS 有一个 GATHER_DICTIONARY_STATS() procedure

标签: oracle oracle12c


【解决方案1】:

根据我的经验,从 user_constraintsuser_cons_columns 中选择的数据字典视图对于几个主要的 Oracle 版本来说都很慢。不仅仅是12c。执行dbms_stats.gather_dictionary_stats; 将下面的第一个查询速度提高了 10-20%。

真正有用的是重写查询以使用/*+materialized*/ 提示从with 子句“表”中选择,而不是直接从user_ 表中选择。

这个查询在我的设置中非常慢,大约 150 秒:(它返回表列表中的所有外键,包括外键两端的表名和列名)

select
  cc.table_name, cc.position, cc.constraint_name, cc.column_name,
  cr.table_name r_table_name, ccr.constraint_name r_constraint_name, ccr.column_name r_column_name
from user_constraints   c
join user_cons_columns  cc on cc.constraint_name=c.constraint_name and
                              cc.owner=c.owner and 
                              cc.table_name=c.table_name
join user_constraints   cr on cr.owner=c.r_owner and
                              cr.constraint_name=c.r_constraint_name and
                              cr.constraint_type in ('P','U')
join user_cons_columns ccr on ccr.constraint_name=cr.constraint_name and
                              ccr.owner=cr.owner and
                              ccr.table_name=cr.table_name and
                              ccr.position=cc.position
where c.constraint_type='R'
and c.table_name in ('TABLE_A', 'TABLE_B', ........a list of about 157 table names.......)
order by cc.table_name, cc.position, constraint_name, column_name, cc.position;

重写后,查询只使用 1-8 秒

with
uc  as (select /*+materialize*/ owner,table_name,constraint_name,constraint_type,r_owner,r_constraint_name  from user_constraints),
ucc as (select /*+materialize*/ owner,table_name,constraint_name,position,column_name from user_cons_columns)
select
  cc.table_name, cc.position, cc.constraint_name, cc.column_name,
  cr.table_name r_table_name, ccr.constraint_name r_constraint_name, ccr.column_name r_column_name
from uc     c
join ucc   cc on cc.constraint_name=c.constraint_name and cc.owner=c.owner and cc.table_name=c.table_name
join uc    cr on cr.owner=c.r_owner and cr.constraint_name=c.r_constraint_name and cr.constraint_type in ('P','U')
join ucc  ccr on ccr.constraint_name=cr.constraint_name and ccr.owner=cr.owner and ccr.table_name=cr.table_name and ccr.position=cc.position
where c.constraint_type='R'
and c.table_name in ('TABLE_A', 'TABLE_B', ........a list of about 157 table names.......)
order by cc.table_name, cc.position, constraint_name, column_name, cc.position;

我还尝试了*,而不是仅在with 表中列出所需的列,但这并没有帮助。我猜这是因为如果要记住/缓存太多数据,Oracle 会忽略 /*+materialize*/ 提示。

【讨论】:

  • 谢谢 - 非常有帮助!
【解决方案2】:

1.收集字典统计信息。

begin
    dbms_stats.gather_dictionary_stats;
end;
/

2。收集固定对象的统计数据。

begin
    dbms_stats.gather_fixed_objects_stats;
end;
/

还有一些罕见的数据字典对象永远不会被分析,除非你特别用dbms_stats.gather_table_stats 调用它们。

3.查找损坏的数据字典对象。some rare cases 字符集问题可能会导致数据字典性能问题。在SELECT 上运行EXPLAIN PLAN 并在谓词中查找任何“奇怪”的东西,例如NLSSORT 会阻止索引访问。

4.查看我的 Oracle 支持。 我之前曾看到过数据字典视图因新版本而降级的错误。有时有一个替代版本的数据字典视图可以解决这个问题。我在 My Oracle Support 上进行了搜索,“Data Dictionary Select Take A Very Long Time in 12c (Doc ID 2251730.1)”可能与此处相关。我无法在此处发布该文章的内容,因此请访问 support.oracle.com 并查看该错误报告中的解决方法。

5.认为自己很幸运。如果你只有一个性能问题,而且速度只有四倍,我认为这是一次成功的升级。

【讨论】:

  • 谢谢,这很有帮助。我已经收集了您建议的统计数据,但还没有看到改进。我也会尝试你的其他建议。我注意到我不是唯一一个举报此community.oracle.com/thread/3703081 的人
【解决方案3】:

我参加这个聚会有点晚了,但正如Burleson 所建议的那样,在您对 Oracle 数据字典的查询中使用 /*+ RULE */ 提示。这有效地关闭了优化器。

Many 已经说过不要使用提示,并且 RULE 提示一直是 deprecated 但它对我的情况有很大的影响。我的一个 DBA_IND_COLUMNS 查询需要 18 MINUTES 来运行,现在只需不到一秒 (Oracle 12cR1)。不知道为什么会这样......

【讨论】:

  • 谢谢!
  • 是的,/*+RULE*/ 也有帮助。
猜你喜欢
  • 2023-03-18
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 2013-12-30
  • 2018-08-29
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多