JDBC automatical query turned to be very slow

后端 未结 5 1929
一向
一向 2021-02-10 10:57

I am maintaining an application creating an Oracle DB via JDBC. Starting from today this query:

SELECT  NULL                                                   AS         


        
相关标签:
5条回答
  • 2021-02-10 11:26

    Data dictionary or fixed object statistics might be old, try re-gathering them:

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

    Even that does not necessarily gather statistics for all system objects. Some objects, like X$KFTBUE, must be gathered manually. Although that's a rare data dictionary problem that may not be relevant here.

    If that doesn't work some next possible steps are looking at tools like SQL Tuning Advisor to create a profile, or using SQL Plan Management to force the optimizer to use a specific plan that has worked before. Tuning a data dictionary query can be very difficult since you don't have much control.

    0 讨论(0)
  • 2021-02-10 11:32

    here is another more graceful solution.. I found that forcing the rule base optimizer with a sql patch also works.. 2 patches are necessary because sometimes the jdbc driver uses :1 and :3 as bind variables and sometimes it uses :2 & :4.. The SQL must match exactly for the patch to work.

    run this in your database as 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;
        /
    
    0 讨论(0)
  • 2021-02-10 11:37

    The query in the question is generated by a call to java.sql.DatabaseMetaData.getExportedKeys() which delegates to oracle.jdbc.OracleDatabaseMetaData.getExportedKeys() to enumerate foreign keys referencing given table.

    As stated in @Jon's answer, Oracle sometimes uses suboptimal plan for this query that may or may not be avoided by gathering statistics.

    Other alternatives if the code can be changed:

    • look at Easiest way to obtain database metadata in Java? for alternative implementation
    • rewrite the query and call it directly

    The second option was chosen by Liquibase project that used to call DatabaseMetaData in older versions. New versions use optimized query with proper joins from 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
    
    0 讨论(0)
  • 2021-02-10 11:40

    I found this way to cheat.. run this as the user you connect with jdbc before you reverse engineer a schema..

    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);  
    

    Then the query in question really screams.. the downside is you have to refresh it from time to time.. maybe make it a materialized view?

    0 讨论(0)
  • 2021-02-10 11:41
    1. Use oracle EXPLAIN PLAN http://docs.oracle.com/cd/B10500_01/server.920/a96533/ex_plan.htm (use the result to find the bottleneck and re-write or change your query to run faster). enter image description here
    2. Make sure you are using indexes on your tables and your indexes are updated.
    3. use partitioning.
    4. clean up some of the data that you don't need anymore
    5. use hibernate if you can (this may not be a easy thing to do if this is a legacy application) because it optimizes your query for you and you won't need to write JDBC query.
    6. Lastly take a look at oracle performance tunning document http://docs.oracle.com/cd/E11882_01/server.112/e41573/perf_overview.htm#PFGRF02503
    0 讨论(0)
提交回复
热议问题