10

我正在使用 Java 1.6、JTDS 1.2.2(也只是尝试 1.2.4 无济于事)和 SQL Server 2005 来创建 CallableStatement 来运行存储过程(不带参数)。我看到运行相同存储过程的 Java 包装器比使用 SQL Server Management Studio 慢 30%。我已经运行了 MS SQL 分析器,两个进程之间的 I/O 差别不大,所以我认为这与查询计划缓存无关。

存储过程不接受任何参数并且不返回任何数据。它使用服务器端游标来计算填充表所需的值。

我看不出从 Java 调用存储过程应该如何增加 30% 的开销,当然它只是一个到数据库的管道,SQL 被发送下来,然后数据库执行它......数据库可以给 Java应用不同的查询计划??

我已经发布到MSDN 论坛和 sourceforge JTDS 论坛(主题:“在 JTDS 中存储 proc 比直接在 DB 中慢”)我想知道是否有人对为什么会发生这种情况有任何建议?

提前致谢,

-詹姆士

(注意不要害怕,一旦我找到解决方案,我会在这里整理我在其他论坛上得到的任何答案)

Java代码片段:

sLogger.info("Preparing call...");
stmt = mCon.prepareCall("SP_WB200_POPULATE_TABLE_limited_rows");
sLogger.info("Call prepared.  Executing procedure...");
stmt.executeQuery();
sLogger.info("Procedure complete.");

我运行了 sql profiler,发现如下:

Java 应用程序:CPU:466,514 读取:142,478,387 写入:284,078 持续时间:983,796

SSMS:CPU:466,973 读取:142,440,401 写入:280,244 持续时间:769,851

(都在分析之前运行 DBCC DROPCLEANBUFFERS,并且都产生正确的行数)

所以我的结论是它们都执行相同的读取和写入,只是它们执行的方式不同,你们怎么看?

事实证明,不同客户端的查询计划有很大不同(Java 客户端在插入期间更新索引,而不是在更快的 SQL 客户端中,此外,它执行连接的方式也不同(嵌套循环 Vs.收集流,嵌套循环与索引扫描,啊!))。为什么会这样,我还不知道(当我找到它的底部时我会重新发布)

结语

我无法让它正常工作。我尝试同质化Java 和 Mgmt studio 客户端之间的连接属性(等)arithabortansi_nulls最终,两个不同的客户端具有非常相似的查询/执行计划(但仍然具有不同的实际 plan_id)。我在 MSDN SQL Server 论坛上发布了我发现的摘要,因为我发现不仅在 JDBC 客户端和管理工作室之间,而且在微软自己的命令行客户端 SQLCMD 之间也存在不同的性能,我还检查了一些更激进的事情,比如网络流量太,或者将存储过程包装在另一个存储过程中,只是为了笑。

我有一种感觉,问题出在游标执行方式的某个地方,它以某种方式导致 Java 进程被挂起,但是为什么不同的客户端应该在没有其他东西运行的情况下产生这种不同的锁定/等待行为并且相同的执行计划在运行中有点超出我的技能(我不是 DBA!)。

结果,我决定 4 天足够任何人的时间浪费在这样的事情上,所以我会勉强围绕它进行编码(如果我说实话,存储过程需要重新编码以增加增量而不是重新编码) - 无论如何每周计算所有数据),并将这个记录下来以体验。我会留下这个问题,非常感谢所有把帽子放在戒指上的人,这一切都很有用,如果有人想出更多的东西,我很想听听更多的选择......如果有人找到这篇文章是在他们自己的环境中看到这种行为的结果,然后希望这里有一些你可以自己尝试的指示,并希望比我们更深入地了解。

我现在准备好我的周末了!

-詹姆士

4

8 回答 8

4

您可以附加 Profiler 并监控事件SQL:BatchCompletedSP:Completed,过滤器的持续时间 > 1000。从 Java 客户端和 SSMS 运行该过程。比较两个事件的读取和写入(Java 与 SSMS)。它们有显着不同吗?这将表明执行路径或计划有很大不同,I/O 也有显着差异。

也尝试捕获两者的Showplan XML事件并比较计划(将事件保存为.sqlplan文件,在SSMS中打开以方便分析)。他们有类似的计划吗?估计与实际(行、倒带、重新绑定)是否存在巨大差异?它们是否具有相同程度的并行性?计划也可以从sys.dm_exec_requests视图中检索。

是否引发了任何警告事件,例如缺少列统计信息、排序警告哈希警告执行警告阻塞进程

关键是您可以使用一整套调查工具。找到差异的根本原因后,您可以将其追溯到 Java 环境设置和 SSMS 环境 (ADO.Net SqlClient) 之间的差异。诸如默认事务隔离级别、ANSI 设置等之类的东西。

于 2009-11-24T16:59:26.950 回答
2

我记得不久前遇到过类似的问题,因为 JTDS 正在默默地将字符串参数转换为 Unicode 或类似的东西。由于该转换,当我们从 SSMS 运行存储过程时,SQL Server 无法使用正在使用的索引。

HIH

于 2010-05-29T19:33:28.297 回答
2

检查:您的问题是两个应用程序(SSMS、Java)对 SQL Server 进行完全相同的调用,而 SQL Server 对每个应用程序的行为不同?如果是这样,我每隔一两年就会遇到这样的事情,它们会伤害我的大脑好几天。

有一次,我最终隔离了每个进程调用,并在 Profiler 中记录整个进程的所有内容。我最终注意到 Login 事件(在 TextData 下)显示了大量信息,如下所示:

-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed

“现有连接”事件也会显示此信息——但是,有时会立即发送后续调用(批处理、RPC,我刚才不记得)[我认为 ISQL 或 OSQL 这样做了] 以立即重置其中一些—— Arithabort 和 Quoted_Identifier 似乎是最喜欢的,其他 SET 选项也会根据应用程序数据库接口使用的任何连接协议的设置或要求进行修改。

另一个:一些设置在“创建”时保留为过程的属性,而其他设置在编译时被考虑在内。一方面,您的连接的 SET 值可能会被创建过程时保存的配置覆盖;另一方面,您的两个连接可能相差很大,以至于为一个过程生成了两个执行计划。(经过充分研究,所有这些信息都可以在系统表和 DMV 中找到。)

简而言之,在我看来,SQL 晦涩难懂的东西把你搞砸了。直到今天,我都讨厌所有这些 goombah 设置。我注意到的事情一直在搞乱他们[我的意思是,真的,哪个傻瓜会为连接池设置implicit_transaction ?但是一旦他们这样做了......] 当地面(规则)不断从你下面改变时,很难建造结构。毕竟,还记得那个家伙说过在沼泽中建造城堡的话……

于 2009-11-25T15:39:56.490 回答
0

If you are looking at the profiler and there is no difference between the executions then the difference must be with the client systems.

4 mins does seem like to long just to prepare a statement to send so the 12 min wait must cause some other effect -- no idea what it is.

于 2009-11-24T16:46:51.673 回答
0

Java 案例是否包括将结果传输到 Java 服务器(网络开销)以及一些 Java 处理?12 分钟的查询可能会产生相当大量的数据。

于 2009-11-24T15:33:23.020 回答
0

我不确定这篇文章是否仍然相关。我们在应用程序中遇到了类似的问题。

在 SQL Management Studio 中运行存储过程与从 ​​JDBC 中运行存储过程的一个关键区别在于事务上下文。如果您在 Java 中使用 ORM,默认情况下存储过程在事务上下文中运行。当您直接在 SQL 管理工作室中运行存储过程时,事务处于关闭状态。有很大的性能差异。

于 2014-06-12T04:19:36.433 回答
-1

抱歉,我没有找到正确的答案,所以我不想将其中任何一个分配为正确的,所以我将这个答案标记为正确,并祝任何遇到类似情况的人好运!

于 2010-02-11T17:53:38.420 回答
-1

您知道 Microsoft 为他们的数据库提供 JDBC 驱动程序吗?

这些可能更高效。

显然..你现在可能已经解决了这个问题。

于 2010-04-22T20:16:16.103 回答