我正在查看一个非常慢的 SQL 查询(源自使用 JBoss 5.1 中部署的 Hibernate 的 Java 应用程序)。这个特定的查询返回了大约 10K 条记录,但仍然需要 40 秒或更长时间。
我最终用数据库嗅探了流量(wireshark 有一个用于 TNS 的解析器)并发现了一些意想不到的东西。当数据来自服务器时,每个结果行都在其自己的 TNS 数据包中。此外,在从数据库发送下一个 TNS 数据包之前,客户端(即应用服务器)会确认每个 TNS 数据包。对于 10K 记录,有 10K 往返来获取数据包并确认它。对性能的影响是巨大的。
这是非常低效的。TCP 允许更大的数据包并具有许多机制(滑动窗口、延迟的 ACK)来减少延迟并增加吞吐量。但是,在这种情况下,是顶部的 TNS 协议添加了自己的协商。
如果我从 Oracle 的 SQL Developer 运行相同的查询,我看不到这种模式。查询在大约 1/10 的时间内完成,无需数千次往返。
简短版本:Oracle 的有线协议 (TNS) 似乎在每个查询结果行一个 TNS 数据包中传递数据,并要求客户端在服务器发送下一个数据包之前确认每个数据包。
我在 [这里][1] 找到了一些关于此的信息(向下滚动到“tnsnames.ora 文件中的 SDU 和 TDU 参数”部分)。
因此我的问题是:是否可以控制 Oracle 驱动程序的行为(我使用的是 10.2.0.4.0)以使 TNS 协议更有效?同样,这是部署在 JBoss 中的非常标准的 J2EE 应用程序。
非常感谢!