5

我正在维护一个通过 JDBC 创建 Oracle DB 的应用程序。从今天开始这个查询:

SELECT  NULL                                                   AS pktable_cat  ,
        p.owner                                                AS pktable_schem,
        p.table_name                                           AS pktable_name ,
        pc.column_name                                         AS pkcolumn_name,
        NULL                                                   AS fktable_cat  ,
        f.owner                                                AS fktable_schem,
        f.table_name                                           AS fktable_name ,
        fc.column_name                                         AS fkcolumn_name,
        fc.position                                            AS key_seq      ,
        NULL                                                   AS update_rule  ,
        DECODE (f.delete_rule, 'CASCADE', 0, 'SET NULL', 2, 1) AS delete_rule  ,
        f.constraint_name                                      AS fk_name      ,
        p.constraint_name                                      AS pk_name      ,
        DECODE(f.deferrable, 'DEFERRABLE',5 ,'NOT DEFERRABLE',7 , 'DEFERRED', 6 ) deferrability
FROM    all_cons_columns pc,
        all_constraints p  ,
        all_cons_columns fc,
        all_constraints f
WHERE   1                      = 1
        AND p.table_name       = :1
        AND p.owner            = :3
        AND f.constraint_type  = 'R'
        AND p.owner            = f.r_owner
        AND p.constraint_name  = f.r_constraint_name
        AND p.constraint_type  = 'P'
        AND pc.owner           = p.owner
        AND pc.constraint_name = p.constraint_name
        AND pc.table_name      = p.table_name
        AND fc.owner           = f.owner
        AND fc.constraint_name = f.constraint_name
        AND fc.table_name      = f.table_name
        AND fc.position        = pc.position
ORDER BY fktable_schem,
        fktable_name  ,
        key_seq

由于某些 oracle 内部结构,它开始变得非常缓慢,因为它似乎对我所有的分支都是一样的。

有人知道一个可能的原因以及如何面对吗?

问候, 农齐奥

4

5 回答 5

8

数据字典或固定对象统计信息可能是旧的,请尝试重新收集它们:

exec dbms_stats.gather_dictionary_stats;
exec dbms_stats.gather_fixed_objects_stats;
alter system flush shared_pool;

即使这样也不一定会收集所有系统对象的统计信息。有些对象,例如X$KFTBUE,必须手动收集。虽然这是一个罕见的数据字典问题,可能与这里无关。

如果这不起作用,那么接下来的一些可能步骤是查看 SQL Tuning Advisor 等工具来创建配置文件,或者使用 SQL 计划管理来强制优化器使用以前有效的特定计划。调整数据字典查询可能非常困难,因为您没有太多控制权。

于 2014-02-18T18:09:39.820 回答
2

这是另一个更优雅的解决方案..我发现使用 sql 补丁强制规则库优化器也有效.. 2 个补丁是必要的,因为有时 jdbc 驱动程序使用 :1 和 :3 作为绑定变量,有时它使用 :2 & : 4.. SQL 必须完全匹配才能使补丁工作。

在您的数据库中以 sysdba 身份运行它。

    begin 
        dbms_sqldiag_internal.i_create_patch ( 
      sql_text =>'SELECT NULL AS pktable_cat,
        p.owner as pktable_schem, p.table_name as pktable_name, 
        pc.column_name as pkcolumn_name, NULL as fktable_cat, f.owner as       
        fktable_schem, f.table_name as fktable_name, 
        fc.column_name as fkcolumn_name, fc.position as key_seq, NULL as 
        update_rule, decode 
        (f.delete_rule, ''CASCADE'', 0, ''SET NULL'', 2, 1) as delete_rule, 
        f.constraint_name as fk_name, p.constraint_name as pk_name, 
        decode(f.deferrable, ''DEFERRABLE'',5 ,''NOT DEFERRABLE'',7 , ''DEFERRED'', 6)  
        deferrability
        FROM all_cons_columns pc, all_constraints p, all_cons_columns fc, 
        all_constraints f
        WHERE 1 = 1 AND p.table_name = :1  AND p.owner = :3 AND 
         f.constraint_type = ''R'' AND p.owner = f.r_owner AND 
         p.constraint_name = f.r_constraint_name AND p.constraint_type = ''P'' 
         AND pc.owner = p.owner AND pc.constraint_name = p.constraint_name AND
         pc.table_name = p.table_name AND fc.owner = f.owner AND 
         fc.constraint_name = f.constraint_name AND 
         fc.table_name = f.table_name AND fc.position = pc.position 
        ORDER BY fktable_schem, fktable_name, key_seq' ,
      hint_text => 'RULE', 
      name => 'jdbcpatch');
    end;
    /

    begin 
        dbms_sqldiag_internal.i_create_patch ( 
      sql_text =>'SELECT NULL AS pktable_cat,
        p.owner as pktable_schem, p.table_name as pktable_name, 
        pc.column_name as pkcolumn_name, NULL as fktable_cat, f.owner as       
        fktable_schem, f.table_name as fktable_name, 
        fc.column_name as fkcolumn_name, fc.position as key_seq, NULL as 
        update_rule, decode 
        (f.delete_rule, ''CASCADE'', 0, ''SET NULL'', 2, 1) as delete_rule, 
        f.constraint_name as fk_name, p.constraint_name as pk_name, 
        decode(f.deferrable, ''DEFERRABLE'',5 ,''NOT DEFERRABLE'',7 , ''DEFERRED'', 6)  
        deferrability
        FROM all_cons_columns pc, all_constraints p, all_cons_columns fc, 
        all_constraints f
        WHERE 1 = 1 AND p.table_name = :2  AND p.owner = :4 AND 
         f.constraint_type = ''R'' AND p.owner = f.r_owner AND 
         p.constraint_name = f.r_constraint_name AND p.constraint_type = ''P'' 
         AND pc.owner = p.owner AND pc.constraint_name = p.constraint_name AND
         pc.table_name = p.table_name AND fc.owner = f.owner AND 
         fc.constraint_name = f.constraint_name AND 
         fc.table_name = f.table_name AND fc.position = pc.position 
        ORDER BY fktable_schem, fktable_name, key_seq' ,
      hint_text => 'RULE', 
      name => 'jdbcpatch2');
    end;
    /
于 2014-03-21T13:35:34.743 回答
2

问题中的查询是通过调用java.sql.DatabaseMetaData.getExportedKeys()委托oracle.jdbc.OracleDatabaseMetaData.getExportedKeys()来枚举引用给定表的外键的。

正如@Jon 的回答中所述,Oracle 有时会为此查询使用次优计划,这可能会或可能不会通过收集统计信息来避免。

如果可以更改代码,则可以使用其他替代方法:

第二个选项是由过去调用旧版本的Liquibase项目选择的。新版本使用来自CORE-1844DatabaseMetaData的正确连接的优化查询:

SELECT NULL AS pktable_cat, p.owner as pktable_schem, 
    p.table_name as pktable_name, pc.column_name as pkcolumn_name,    
    NULL as fktable_cat, f.owner as fktable_schem, f.table_name as fktable_name,    
    fc.column_name as fkcolumn_name, fc.position as key_seq, NULL as update_rule,    
    decode (f.delete_rule, 'CASCADE', 0, 'SET NULL', 2, 1) as delete_rule,    
    f.constraint_name as fk_name, p.constraint_name as pk_name,    
    decode(f.deferrable, 'DEFERRABLE', 5, 'NOT DEFERRABLE', 7, 'DEFERRED', 6) deferrability  
FROM    all_constraints p
INNER JOIN  all_cons_columns pc ON pc.owner = p.owner    
    AND pc.constraint_name = p.constraint_name    
    AND pc.table_name = p.table_name    
INNER JOIN all_constraints f ON p.owner = f.r_owner    
    AND p.constraint_name = f.r_constraint_name
INNER JOIN all_cons_columns fc ON fc.owner = f.owner    
    AND fc.constraint_name = f.constraint_name
    AND fc.table_name = f.table_name
    AND fc.position = pc.position
WHERE p.owner = :jdbcSchemaName
    AND p.constraint_type in ('P', 'U')    
    AND f.constraint_type = 'R'    
ORDER BY fktable_schem, fktable_name, key_seq
于 2015-12-03T15:41:16.573 回答
1

我发现了这种作弊方式。在对架构进行反向工程之前,以与 jdbc 连接的用户身份运行它。

CREATE TABLE all_constraints AS
  SELECT owner,
         constraint_name,
         constraint_type,
         table_name,
         r_owner,
         r_constraint_name,
         delete_rule,
         status,
         deferrable,
         deferred,
         validated,
         generated,
         bad,
         rely,
         last_change,
         index_owner,
         index_name,
         invalid,
         view_related
  FROM   all_constraints;

CREATE TABLE all_cons_columns AS
  SELECT *
  FROM   all_cons_columns;

CREATE INDEX ac1
  ON all_constraints (owner, constraint_name, table_name);

CREATE INDEX acc1
  ON all_cons_columns (owner, constraint_name, table_name);  

然后有问题的查询真的很尖叫..缺点是你必须不时刷新它..也许让它成为一个物化视图?

于 2014-03-21T13:04:04.383 回答
0
  1. 使用 oracle EXPLAIN PLAN http://docs.oracle.com/cd/B10500_01/server.920/a96533/ex_plan.htm (使用结果找到瓶颈并重新编写或更改查询以更快地运行)。 在此处输入图像描述
  2. 确保您在表上使用索引并且索引已更新。
  3. 使用分区。
  4. 清理一些你不再需要的数据
  5. 如果可以,请使用 hibernate(如果这是一个遗留应用程序,这可能不是一件容易的事情),因为它会为您优化查询,并且您不需要编写 JDBC 查询。
  6. 最后看一下 oracle 性能调优文档http://docs.oracle.com/cd/E11882_01/server.112/e41573/perf_overview.htm#PFGRF02503
于 2014-02-18T16:41:14.333 回答