JDBC automatical query turned to be very slow

后端 未结 5 1928
一向
一向 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: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
    

提交回复
热议问题