3

我们注意到性能并不出色,但并没有给我们带来太多困扰,因为它是一个后台进程,然后我们的 DBA 联系了我们,他们告诉我们每个存储过程调用都跨越了第二个调用,以从数据库中获取元数据。

显然,在我们的代码中,我们没有进行任何此类调用,不,我们没有使用任何可能在幕后发出它们的 ORM 框架。

这是我们的设置: - 独立(无容器)Java 应用程序 - spring-jdbc-3.2.2 用于数据访问 - 我们使用 Microsoft JDBC Driver 4.0 for SQL Server - 我们使用以下语法:CALL SPROC_NAME(: PAR_1)

非常感谢有关如何删除此额外调用的任何指示。我无法打开 SQL Server 驱动程序的日志记录,所以下一步是尝试调试 Spring JDBC 代码。

谢谢,MV

4

2 回答 2

1

就像我说的,每次存储过程调用(使用 PreparedStatement)都会导致对数据库的 2 次调用,第一次调用非常昂贵:exec sp_sproc_columns @procedure_name =SPROC_NAME,@ODBCVer=3(元数据调用)EXEC SPROC_NAME @P0,@P1, @P2、@P3(实际调用)

在阅读了以下线程之后,我们终于有了一些可以使用的东西: 为什么调用存储过程总是在调用 sp_sproc_columns 之前?

尽管我们使用的是 JDBC 而不是 ADO.NET,但问题似乎与我们的非常相似,因此我们认为值得一试。

更改到位后,数据库中的跟踪会话确认第一个调用不再存在于日志中。

以前我们将 Map 作为参数传递。当我们切换到 Map 并指定正确的数据类型时,我们开始看到性能改进。

简而言之,如果驱动程序拥有关于参数的所有数据(实际上是元数据),那么它不会发出元数据调用。

于 2013-07-26T22:01:04.863 回答
1

这个问题发布已经有一段时间了;但是,考虑到我在工作中遇到了这个问题并且我花了很长时间才弄清楚,我会留下我的答案。希望它可以帮助某人。

简短回答:不要在过程调用中使用命名参数。请改用有序参数。

长答案:使用命名参数时,JDBC 驱动程序首先发出对“sp_sproc_columns”过程的调用。驱动程序发出此调用以获取过程中参数的名称并运行一些验证以检查名称是否正确。它稍后会替换查询中的命名参数并将它们按正确的顺序放置。一旦确定了正确的顺序,驱动程序就会使用有序参数发出对过程的调用。

查看源代码中的调用。https://github.com/Microsoft/mssql-jdbc/blob/dev/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerCallableStatement.java#L1254

于 2018-12-12T05:05:42.597 回答