簡體   English   中英

JDBC自動查詢變得非常慢

[英]JDBC automatical query turned to be very slow

我正在維護一個通過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內部構件開始變得非常慢,因為它似乎對我所有的分支都是一樣的。

有人知道一個可能的原因以及如何面對這個問題嗎?

此致,Nunzio

數據字典或固定對象統計信息可能很舊,請嘗試重新收集它們:

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

即使這樣也不一定會收集所有系統對象的統計信息。 必須手動收集某些對象,如X$KFTBUE 雖然這是一個罕見的數據字典問題,可能與此無關。

如果這不起作用,則下一步可能的步驟是查看SQL Tuning Advisor等工具來創建配置文件,或使用SQL計划管理強制優化器使用以前工作過的特定計划。 調整數據字典查詢可能非常困難,因為您沒有太多控制權。

這是另一個更優雅的解決方案..我發現強制帶有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;
    /

問題中的查詢是通過調用java.sql.DatabaseMetaData.getExportedKeys()生成的,該調用委托給oracle.jdbc.OracleDatabaseMetaData.getExportedKeys()以枚舉引用給定表的外鍵。

正如在@ Jon的回答中所述,Oracle有時會對此查詢使用次優計划,這可能會或可能不會通過收集統計信息來避免。

如果代碼可以更改的其他替代方法:

第二個選項是由Liquibase項目選擇的, 項目曾用於在舊版本中調用DatabaseMetaData 新版本使用來自CORE-1844的適當連接的優化查詢:

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

我發現這種方式作弊..在你反向設計一個模式之前,以你用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);  

然后有問題的查詢真的尖叫..缺點是你必須不時刷新它...也許使它成為物化視圖?

  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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM