Oracle
 sql >> Datenbank >  >> RDS >> Oracle

JDBC mit langsamem Spring-Metadatenabruf von Oracle

Nachdem ich die tatsächliche Kommunikation zwischen Client und Server zurückentwickelt habe, kann ich zeigen, dass Oracles DatabaseMetaData.getColumns()-Methoden die folgende SQL-Abfrage senden (obwohl sich dies mit ODBC-Treiberversionen und -einstellungen ändern kann):

    declare
    in_owner varchar2(128);
    in_name varchar2(128);
    in_column varchar2(128);
    xyzzy SYS_REFCURSOR;
    begin
    in_owner := :1;  // Which resolves to the schema (user) name supplied
    in_name := :2;   // Which resolves to the table name supplied
    in_column := :3; // Which gets set to '%';
    open xyzzy for
    SELECT NULL AS table_cat,
        t.owner AS table_schem,
        t.table_name AS table_name,
        t.column_name AS column_name,
    DECODE(  (SELECT a.typecode
        FROM ALL_TYPES A
        WHERE a.type_name = t.data_type),
    'OBJECT', 2002,
    'COLLECTION', 2003,
    DECODE(substr(t.data_type, 1, 9),
        'TIMESTAMP',
        DECODE(substr(t.data_type, 10, 1),
            '(',
            DECODE(substr(t.data_type, 19, 5),
                'LOCAL', -102, 'TIME ', -101, 93),
            DECODE(substr(t.data_type, 16, 5),
            'LOCAL', -102, 'TIME ', -101, 93)),
        'INTERVAL ',
        DECODE(substr(t.data_type, 10, 3),
        'DAY', -104, 'YEA', -103),
        DECODE(t.data_type,
        'BINARY_DOUBLE', 101,
        'BINARY_FLOAT', 100,
        'BFILE', -13,
        'BLOB', 2004,
        'CHAR', 1,
        'CLOB', 2005,
        'COLLECTION', 2003,
        'DATE', 93,
        'FLOAT', 6,
        'LONG', -1,
        'LONG RAW', -4,
        'NCHAR', -15,
        'NCLOB', 2011,
        'NUMBER', 2,
        'NVARCHAR', -9,
        'NVARCHAR2', -9,
        'OBJECT', 2002,
        'OPAQUE/XMLTYPE', 2009,
        'RAW', -3,
        'REF', 2006,
        'ROWID', -8,
        'SQLXML', 2009,
        'UROWI', -8,
        'VARCHAR2', 12,
        'VARRAY', 2003,
        'XMLTYPE', 2009,
        1111)))
    AS data_type,
        t.data_type AS type_name,
        DECODE (t.data_precision, null,
            DECODE(t.data_type, 'NUMBER',
                DECODE(t.data_scale, null, 0 , 38),
                    DECODE (t.data_type, 'CHAR', t.char_length, 'VARCHAR', t.char_length, 'VARCHAR2', t.char_length, 'NVARCHAR2', t.char_length, 'NCHAR', t.char_length, 'NUMBER', 0, t.data_length) ), t.data_precision)
        AS column_size,
        0 AS buffer_length,
        DECODE (t.data_type, 'NUMBER', DECODE(t.data_precision, null, DECODE(t.data_scale, null, -127 , t.data_scale), t.data_scale), t.data_scale) AS decimal_digits,
        10 AS num_prec_radix,
        DECODE (t.nullable, 'N', 0, 1) AS nullable,
        NULL AS remarks,
        t.data_default AS column_def,
        0 AS sql_data_type,
        0 AS sql_datetime_sub,
        t.data_length AS char_octet_length,
        t.column_id AS ordinal_position,
        DECODE (t.nullable, 'N', 'NO', 'YES') AS is_nullable,
        null as SCOPE_CATALOG,
        null as SCOPE_SCHEMA,
        null as SCOPE_TABLE,
        null as SOURCE_DATA_TYPE,
        'NO' as IS_AUTOINCREMENT,
        t.virtual_column as IS_GENERATEDCOLUMN
    FROM all_tab_cols t
    WHERE t.owner LIKE in_owner ESCAPE '/'
    AND t.table_name LIKE in_name ESCAPE '/'
    AND t.column_name LIKE in_column ESCAPE '/'
    AND t.user_generated = 'YES'
    ORDER BY table_schem, table_name, ordinal_position;
    end;

Sie können verstehen, warum das etwas langsam sein könnte, besonders da die Tabellen ALL_TAB_COLS und ALL_TYPES jeweils Tausende von Datensätzen lang sein können. Obwohl Oracle damit kämpft, den allerersten Aufruf (Minuten) auszuführen, geben nachfolgende Aufrufe fast sofort Ergebnisse zurück. Dies ist ein klassisches Leistungsproblem bei der Tabellenverknüpfung, bei dem, obwohl eine Teilmenge von Daten erforderlich ist, die Engine vorher die gesamte Datenmenge verknüpft Berechnung und Lieferung der erforderlichen Teilmenge. Anschließend funktioniert das Zwischenspeichern von Daten/Ergebnissen, um die Leistung nachfolgender Abfragen zu verbessern.

Die bessere Lösung könnte darin bestehen, get_ddl() zu verwenden und die zurückgegebene Tabellendefinition gemäß dieser Thread .

Alternativ Möglicherweise können Sie die Metadaten einer Tabelle schneller abfragen, indem Sie eine Dummy-Abfrage ausführen und dann resultSetMetadata wie folgt verwenden (Hinweis:Metadaten für Spaltenbemerkungen sind möglicherweise nicht sofort verfügbar):

    ResultSet rs = connection.CreateStatement.executeQuery("SELECT * from MyTable WHERE 1=0");
    ResultSetMetaData md = rs.getMetaData();
    for (int ix = 1; ix <= md.getColumnCount(); ix++)
    {
      int colSize = md.getPrecision(ix);
      String nativeType = md.getColumnTypeName(ix);
      int jdbcType = md.getColumnType(ix);
      // and so on....
    }