带有 Spring 的 JDBC 缓慢元数据获取 Oracle
我正在使用 Spring JdbcUtils.extractDatabaseMetaData() 方法来分析数据库。该函数调用回调并移交 DatabaseMetaData
对象。该对象提供getColumns(String Catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
。
我这样称呼它 getColumns("",TABLE_OWNER_USERNAME,null,null)
并得到 400 列结果。这些正是我想要的结果,但请求需要超过 1 分钟。
我可以以某种方式优化这个查询以使其更快吗?拉取 400 行应该在 1 秒内完成,而不是一分钟。
编辑:我不怀疑 Spring 部分很慢。更仔细的分析表明,获取DatabaseMetaData
需要几秒钟,但执行getColumns()
需要很长时间。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对客户端和服务器之间的实际通信进行逆向工程后,我可以发现 Oracle 的 DatabaseMetaData.getColumns() 方法发送以下 SQL 查询(尽管这可能会因 ODBC 驱动程序版本和设置而改变):
您可以理解为什么这可能有点慢,特别是 ALL_TAB_COLS 和 ALL_TYPES 表都可以有 1000 条记录长。然而,尽管 Oracle 努力执行第一次调用(几分钟),但后续调用几乎立即返回结果。这是一个典型的表连接性能问题,即使需要数据子集,引擎也会在计算和提供所需子集之前连接整个数据集。随后的数据/结果缓存可提高后续查询的性能。
更好的解决方案可能是使用 get_ddl() 并根据 此线程。
或者,您可以通过执行虚拟查询然后使用 resultSetMetadata 更快地查询表上的元数据,如下所示(注意:列备注元数据可能无法立即可用):
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):
也许这是查询 ALL_TAB_COLUMNS 的更好方法。这是一个示例:
如果您需要按表过滤,只需添加“ AND TABLE_NAME = ?”将sql和tableName作为另一个参数。
希望有帮助。
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.