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