I am using the Spring JdbcUtils.extractDatabaseMetaData()
method to analyze the database. The function calls a callback and hands over a DatabaseMetaData
object. This object provides the getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
.
I call it like this getColumns("",TABLE_OWNER_USERNAME,null,null)
and get 400 columns as a result. These are exactly the results that I want, but the request takes over 1 minute.
Can I somehow optimize this query to be fast? Pulling 400 rows should happen in 1 seconds and not one minute.
EDIT: I don't suspect the Spring part being slow. Closer analysis showed that fetching the DatabaseMetaData
takes a few seconds butexecuting the getColumns()
takes really long.
Maybe it's a better approach to query ALL_TAB_COLUMNS. Here is an example:
If you need to filter by table simply add " AND TABLE_NAME = ?" to sql and tableName as another parameter.
Hope it helps.
Having reverse engineered the actually communications between client and server I can reveal that Oracle's DatabaseMetaData.getColumns() methods sends the following SQL query (though this may change with ODBC driver versions and settings):
You can appreciate why that might be a bit slow, especially as the ALL_TAB_COLS and ALL_TYPES tables can each be 1000's of records long. Nevertheless while Oracle struggles to execute the first ever invocation (minutes) subsequent calls return results almost instantly. This is a classic table-join performance issue where even though a subset of data is required the engine joins the whole dataset before calculating and delivering the required subset. Subsequently data/results caching works to improve the performance of subsequent queries.
The better solution might be to use get_ddl() and parse the returned table definition as per this thread.
Alternatively you may be able to query the metadata on a table faster by executing a dummy query then using resultSetMetadata as follows (Note: column remarks metadata may not be immediately available):