我们正在从 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
Run Code Online (Sandbox Code Playgroud)
难道这只是收集统计数据的问题吗?
根据我的经验,对于几个主要的 Oracle 版本,从user_constraints和user_cons_columns以及其他数据字典视图中进行选择的速度很慢。不只是12c。这样做将dbms_stats.gather_dictionary_stats;第一个查询的速度提高了 10-20%。
但真正有用的是使用提示重写查询以从 with子句“表”中选择/*+materialized*/,而不是直接从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;
Run Code Online (Sandbox Code Playgroud)
重写此后,查询仅使用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;
Run Code Online (Sandbox Code Playgroud)
我也尝试*不只列出with表中所需的列,但这没有帮助。我猜这是因为/*+materialize*/如果要记住/缓存太多数据,Oracle 会忽略提示。
| 归档时间: |
|
| 查看次数: |
2032 次 |
| 最近记录: |